4

I am a fairly experienced LaTeX user. Now, I am trying to get into learning the internals of LaTeX packages and classes. I do not know much about TeX coding. I thought a good beginning would be to try to make a small package that typesets problems and solutions. I have already looked at many such packages like examdesign, exams, answers etc. For a beginner, I understand the overall logic in some of these classes/packages, but not all the details. So, I wanted to do things a bit myself to gain more insight. Here is my attempt at a simple package which I call it qakeysoln:

%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%
% This is file 'qakeysoln.sty', version 1.0, May 2015.                     %
%                                                                          %
% This package and accompanying files may be distributed and/or            %
% modified under the conditions of the LaTeX Project Public License,       %
% either version 1.3 of this license or any later version. The latest      %
% version of this license is in http://www.latex-project.org/lppl.txt      %
% and version 1.3 or later is part of all distributions of LaTeX           %
% version 2005/12/01 or later.                                             %
%                                                                          %
% The LPPL maintenance status of this software is 'author-maintained'.     %
%                                                                          %
% This software is provided 'as it is', without warranty of any kind,      %
% either expressed or implied, including, but not limited to, the          %
% implied warranties of merchantability and fitness for a particular       %
% purpose.                                                                 %
%                                                                          %
% Copyright (c) 2015 Rav Bell.             %
%++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++%

\@ifpackageloaded{newenviron}{}{\RequirePackage{newenviron}}
\@ifpackageloaded{etoolbox}{}{\RequirePackage{etoolbox}}
\StyleFilePurpose{For formatting questions, optionally answer keys/hints, and solutions}
\ProvidesPackage{qakeysoln}[2015/05/11 Rav Bell]
\NeedsTeXFormat{LaTeX2e}[2011/06/27]



% Initialize a global list to hold all the solutions 
\listxadd{\qaks@solutionlist}{}

% Provide a command to the user to list all the solutions 
\newcommand{\thesolutionlist}{%
\show\qaks@solutionlist
\begin{enumerate}%
\renewcommand*{\do}[1]{\item ##1}
\dolistloop{\qaks@solutionlist}
\end{enumerate}
}

% Define the question environment 
% to be used inside a bigger environment like essayq, shortanswer etc.
\newcommand{\qaks@DefineQuestion}{
\newenvironment{question}{\item 

%Use a temporary list \temp@solnlist to store solutions. This is useful if several
%solution environments are defined by a user within one question
%environment (perhaps as alternate solutions). Then all these are
%stored in a single temp list and then the list is appended to the
%global list

% Define solution environment inside question env so that it cannot be    
% used outside of the question environment 
\newenviron{solution}{}{\xappto{\temp@solnlist}{\solutionbody {\@@par}}} %



}{%

%Add the solutions collected to the global list of solutions
\listxadd{\qaks@solutionlist}{%
% noexpand so that I want it to expand later when typesetting the whole
%solution list. But note that \temp@solnlist is expanded right here.
\noexpand\begin{enumerate}
  \forlistloop{\noexpand\item\noexpand[\noexpand]}{\temp@solnlist}
\noexpand\end{enumerate}
}

%delete all the solutions in the temporary list for the current question
\gdef\temp@solnlist{}

}

}

% define a essay question environment:
\newenvironment{essayq}{%
\begin{enumerate}%
\qaks@DefineQuestion
}{\end{enumerate}}

Here is a sample LaTeX file that I used to test this.

\documentclass[a4paper]{article}
\usepackage{qakeysoln}



\begin{document}
\title{A sample file to demonstrate the Questions and Solns}
\maketitle


\section{Questions}
\label{sec:questions}


\begin{essayq}



\begin{question}

  What is $2\times3$?

 \begin{solution}
   $ 3 + 3 = 6$
 \end{solution}

\end{question}

\begin{question}
  What is $3\times2$?  


  \begin{solution}
    Here is the solution: $2 + 2 + 2 = 6$

    Note that this was such a trivial solution that it required no
    explanations.    
  \end{solution}

  \begin{solution}  
    This is an \textbf{alternative solution}:

    $((2+2)+2) = 6$
  \end{solution}



\end{question}

\end{essayq}





\clearpage
\section{Solutions}
\label{sec:solns}

\thesolutionlist


\end{document}

This throws an error when compiling. The problem, it turns out, is the \textbf{alternative solution}. If I remove \textbf. It works just fine. I tried so many different things including \noexpand and \protect. But nothing worked. I felt like I hit a hard wall here. I am pretty sure this must be something trivial for some of the experts here. I am looking forward to understanding and finding a solution to this here.

  • Welcome to TeX.SX! You can have a look at our starter guide to familiarize yourself further with our format. – Martin Schröder May 18 '15 at 10:22
  • \expandonce{\solutionbody} instead of \solutionbody in the argument to \xappto seems to be a good idea. However, I find the package code unreadable. – egreg May 18 '15 at 15:41
3

You have too deep expansion in two places: add \expandonce.

First:

\newenviron{solution}{}{\xappto{\temp@solnlist}{\expandonce{\solutionbody} {\@@par}}} %

Second:

\listxadd{\qaks@solutionlist}{%
%noexpand so that I want it to expand later when typesetting the whole
%solution list. But note that \temp@solnlist is expanded right here.
\noexpand\begin{enumerate}
  \forlistloop{\noexpand\item[]}{\expandonce{\temp@solnlist}}
\noexpand\end{enumerate}       

(I removed a couple of useless \noexpand tokens).

Another error:

\renewcommand{\do}[1]{\item ##1}

You have \renewcommand* that doesn't allow \par tokens in the argument.


Do yourself a favor and indent your code. Avoid blank lines in the body of a definition, they become \par tokens that can be unwanted.

  • Thanks so much! \renewcommand* was a nice catch. I had cut and paste this small part from the manual and overlooked it. Now everything works as I expect. Your suggestions on coding style is well taken. – RavBell May 19 '15 at 4:30

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.