% \begin{meta-comment}
%
-% $Id: exercise.dtx,v 1.1 2002/02/03 20:49:03 mdw Exp $
+% $Id: exercise.dtx,v 1.2 2003/09/05 16:10:41 mdw Exp $
%
% Exercises
%
-% (c) 2001 Mark Wooding
-%
-%----- Revision history -----------------------------------------------------
-%
-% $Log: exercise.dtx,v $
-% Revision 1.1 2002/02/03 20:49:03 mdw
-% Checkin for new build system.
-%
+% (c) 2003 Mark Wooding
%
% \end{meta-comment}
%
% \begin{meta-comment} <general public licence>
%%
%% exercise package -- useful macros for setting exercises with answers
-%% Copyright (c) 2001 Mark Wooding
+%% Copyright (c) 2003 Mark Wooding
%%
%% This program is free software; you can redistribute it and/or modify
%% it under the terms of the GNU General Public License as published by
%% the Free Software Foundation; either version 2 of the License, or
%% (at your option) any later version.
-%%
+%%
%% This program is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
%% GNU General Public License for more details.
-%%
+%%
%% You should have received a copy of the GNU General Public License
%% along with this program; if not, write to the Free Software Foundation,
%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
% \begin{meta-comment} <Package preambles>
%<+package>\NeedsTeXFormat{LaTeX2e}
%<+package>\ProvidesPackage{exercise}
-%<+package> [2001/09/21 1.0 Exercies with answers]
+%<+package> [2003/08/25 1.1 Exercies with answers]
% \end{meta-comment}
%
-% \CheckSum{236}
+% \CheckSum{271}
%% \CharacterTable
%% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
\input{mdwtools}
\describespackage{exercise}
\let\epsilon\varepsilon
+\errorcontextlines\maxdimen
\mdwdoc
%</driver>
%
%\end{demo}
% \end{figure}
%
+% \DescribeMacro\skipanswer
+% The |\skipanswer| command is similar, but just skips over the answer rather
+% than writing it to the output file. It does nothing at all with counters
+% -- it's as if there was no answer given at all.
+%
+% It's OK to use commands like |\answer| and |\skipanswer| in your own
+% macros as long as they're the \emph{last} token. You can therefore say
+% something like
+%\begin{verbatim}
+%\newcommand{\evenanswer}{%
+% \ifthenelse%
+% {\isodd{\value{exercise}}}%
+% {\answer}%
+% {\skipanswer}%
+%}
+%\end{verbatim}
+% to get just the answers to the odd-numbered problems. (If you don't like
+% \package{ifthen} then you'll need to play with |\expandafter| for a bit.)
+%
% \subsection{The answers file}
%
% \DescribeMacro\answrite
%\answers
%\end{demo}
%
+% The |\answers| command has an optional argument, which is the file to read
+% in. This allows you to make `answer booklet' documents, by saying
+% something like
+%\begin{verbatim}
+%\answers[otherdoc]
+%\end{verbatim}
+% If you don't give a file extension, then |.ans| is appended automatically.
+%
% \implementation
-%
+%
%
%^^A-------------------------------------------------------------------------
% \section{Implementation}
%
% \subsection{Initialization}
%
-% The \textsf{within} option is handled by the \package{keyval} package.
+% The \textsf{within} option is handled by the \package{mdwkey} package.
%
% \begin{macrocode}
-\RequirePackage{keyval}
+\RequirePackage{mdwkey}
% \end{macrocode}
%
% \begin{macro}{\ex@within}
%
% \begin{macrocode}
\let\ex@within\relax
-\define@key{ex}{within}{%
+\mkdef{exercise:opts}{within}{%
\def\ex@within{%
\@addtoreset{exercise}{#1}%
\toks@\expandafter{\csname the#1\expandafter\endcsname%
%
% \begin{macro}{\ex@opts}
%
-% The |\ex@opts| macro just runs the \package{keyval} kit to parse an option
+% The |\ex@opts| macro just runs the \package{mdwkey} kit to parse an option
% string.
%
% \begin{macrocode}
-\def\ex@opts{\setkeys{ex}}
+\def\ex@opts{\mkparse{exercise:opts}}
% \end{macrocode}
% \end{macro}
%
% \end{macrocode}
% \end{macro}
%
+% \begin{macro}{\skipanswer}
+%
+% This is much simpler.
+%
+% \begin{macrocode}
+\let\skipanswer\ignore
+% \end{macrocode}
+% \end{macro}
+%
% \begin{macro}{\answers}
%
% The |\answers| macro closes the file, makes sure that future
%
% \begin{macrocode}
\def\answers{%
+ \@ifnextchar[{\answers@i\input}{\answers@i\@input[\ex@ansfilename]}%
+}
+\def\answers@i#1[#2]{%
\immediate\closeout\ex@ansfile%
\global\let\answrite\exerr@toolate%
- \input{\ex@ansfilename}%
+ \ex@withext{#1}{#2}{ans}%
+}
+\def\q@delim{\q@delim}
+\def\ex@withext#1#2#3{%
+ \edef\next@##1{\noexpand\ex@ext@i{##1}{#2}{#3}#2.\noexpand\q@delim}%
+ \next@{#1}%
+}
+\def\ex@ext@i#1#2#3#4.#5\q@delim{%
+ \ifx\q@delim#5\q@delim\def\next@{#1{#2.#3}}%
+ \else\def\next@{#1{#2}}\fi%
+ \next@%
}
% \end{macrocode}
% \end{macro}
%
% The \env{parlist} environment is a trimmed-down version of a normal list.
% We todge the |\item| command, make |\list| and |\trivlist| make errors, and
-% do various normal list things.
+% do various normal list things.
%
% \begin{macrocode}
\def\parlist#1#2{%
\def\exerr@parlist{%
\PackageError{exercise}{You can't nest a `list' inside a `parlist'.}{%
I've found a `list' or `trivlist' environment nested inside^^J%
- a `parlist'. This isn't allowed.%
+ a `parlist'. This isn't allowed. You're probably doomed now.%
}%
}
%</package>