7

I would like to generate two PDFs from an exam document:

I currently do the following

  1. Add answers to the document class

    \documentclass[french,a4paper,addpoints,11pt,answers]{exam}
    
  2. Build and rename

    latexmk -xelatex foo.tex && mv foo.pdf foo-solution.pdf
    
  3. Remove answers from the document class and rebuild

    latexmk -xelatex foo.tex
    

Is there a better way to do everything from the command line?

3 Answers 3

6

Change the first line to

\documentclass[french,a4paper,addpoints,11pt,\ANSWERS]{exam}

and compile the document with

latex -jobname foo-without-answers '\def\ANSWERS{}\input{foo}'

and

latex -jobname foo-with-answers '\def\ANSWERS{answers}\input{foo}'

respectively.

Or maybe more flexibly, define a switch that you can use throughout the document (with a suggestion by Ulrich Diez in the comments).

\ifANSWERS\PassOptionsToClass{answers}{exam}\fi
\documentclass[french,a4paper,addpoints,11pt]{exam}

Compile with:

latex -jobname foo-without-answers '\newif\ifANSWERS\input{foo}'

and

latex -jobname foo-with-answers '\newif\ifANSWERS\ANSWERStrue\input{foo}'
2
  • @UlrichDiez Thanks, added.
    – gernot
    Commented Oct 5, 2021 at 13:05
  • @UlrichDiez Fixed. On the positive side, people will at least remember you as the guy with the unusual name. That is more than Herr Müller can hope for.
    – gernot
    Commented Oct 5, 2021 at 13:24
4

If the option answers is not needed as a global option that would be applied during the loading of whatsoever packages also, but is to be applied only during the loading of the documentclass exam, then you probably can create a .tex-file, let's call it test.tex, where the answers-option is not given, but which creates an auxiliary file test-solutions.tex with the following content:

\PassOptionsToClass{answers}{exam}%
\input test.tex

Then you can first compile/build test.tex and then test-solutions.tex.

Something like:

%==========This snippet creates \jobname-solutions.tex only
%          in case both it does not already exist and
%          \jobname does not contain the phrase "-solutions".
%
%          This snippet could go into an input-file on its own
%          which is to be loaded via \input right before the
%          \documentclass-command.===============================================
\begingroup\makeatletter
\newcommand\GobbleToNamePostfix[1]{%
   \long\def\GobbleToNamePostfix##1#1{}%
   \expandafter\endgroup
   \ifcat$\detokenize\expandafter\expandafter\expandafter{%
                     \expandafter\GobbleToNamePostfix\jobname#1}$%
   \else\expandafter\@gobble\fi
   {%
     % \jobname does not contain the phrase #1:
     \IfFileExists{\jobname#1.tex}{}{%
       \begingroup
       \immediate\openout\@auxout\jobname#1.tex
       \immediate\write\@auxout{%
          \string\PassOptionsToClass{answers}{exam}\@percentchar
       }%
       \immediate\write\@auxout{\string\input\space\jobname.tex}%
       \immediate\closeout\@auxout
       \endgroup
     }%
     %%
     %% If \write18 is enabled, e.g., by calling the compiler
     %% with the --shell-escape-option, like
     %%     latexmk -shell-escape -xelatex test.tex
     %% , then here you can do a call to the shell for
     %% building \jobname#1.tex/test-solutions.tex:
     %%
     %\RequirePackage{shellesc, iftex}%
     %\ShellEscape{%
     %  latexmk
     %  -\ifluatex lua\fi\ifpdftex pdf\fi\ifxetex xe\fi latex \jobname#1.tex%
     %}%
   }%
}%
\begingroup
%-------------------------------------------------------------------------------
% Here goes the phrase to append to name of .tex-file also delivering solutions:
\renewcommand\GobbleToNamePostfix{-solutions}%
%-------------------------------------------------------------------------------
\@onelevel@sanitize\GobbleToNamePostfix
\expandafter\endgroup\expandafter
\GobbleToNamePostfix\expandafter{\GobbleToNamePostfix}%
%==================== end of snippet ===========================================
%
%\show\GobbleToNamePostfix %yields: > \GobbleToNamePostfix=undefined.
%
\documentclass[french,a4paper,addpoints,11pt]{exam}
\usepackage[T1]{fontenc}
\usepackage{babel}
\makeatletter
\@ifclasswith{exam}{answers}{\def\Answertext{With Answers.}}%
                            {\def\Answertext{Without Answers.}}%
\makeatother
\begin{document}
\Answertext
\begin{questions}
\question[10]Why is there air?
\begin{solution}
Because nobody breathed it away yet.
\end{solution}
\end{questions}
\end{document}

When saving this as test.tex and compiling it, you get test.pdf:

enter image description here

and test-solutions.tex:

\PassOptionsToClass{answers}{exam}%
\input test.tex

When compiling test-solutions.tex, then you get test-solutions.pdf:

enter image description here

Alternatively uncomment/activate the lines

%\RequirePackage{shellesc, iftex}%
%\ShellEscape{%
%  latexmk
%  -\ifluatex lua\fi\ifpdftex pdf\fi\ifxetex xe\fi latex \jobname#1.tex%
%}%

to be

\RequirePackage{shellesc, iftex}%
\ShellEscape{%
  latexmk
  -\ifluatex lua\fi\ifpdftex pdf\fi\ifxetex xe\fi latex \jobname#1.tex%
}%

and just compile test.tex via
latexmk -shell-escape -xelatex test.tex.

This way test.pdf and test-solutions.pdf should be created in one go.

3

If you can live with making a single PDF with the different versions on separate pages, there is a simple solution.

Create a command that only shows the answers if a boolean switch is true. Then save the whole document in a macro that calls that command. Now you can print the document twice, once with answers and once without, just by calling the document macro twice and resetting the boolean switch in between.

\documentclass{article}
\newif\ifanswers
\NewDocumentCommand{\QA}{ m m }{#1 \ifanswers(#2)\fi}
\NewDocumentCommand{\doc}{}{%
  \begin{enumerate}
    \item \QA{Who?}{Him.}
    \item \QA{When?}{Then.}
  \end{enumerate}
}
\begin{document}
\answersfalse\doc{}
\clearpage
\answerstrue\doc{}
\end{document}

You must log in to answer this question.

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