# [OS X TeX] OT-latex file management

Ross Moore ross at ics.mq.edu.au
Thu Apr 29 04:16:25 EDT 2004

Hi Themis, and others

On 29/04/2004, at 6:29 AM, Chris Goedde wrote:

>>> OT-latex file management
>>
>>> Only problem, I would have to maintain a couple hundred problems in
>>> separate files.
>>
>> I haven't followed the whole discussion here, but extracting selected
>> problems from the file containing the couple hundred problems may be
>> workable -- i.e. separate each problem in the big file with
>>
>> %SomeSeparator
>>
>> and copy out only the wanted problems from the big file with a filter
>> --
>
> Maybe I'm a bit dense, but couldn't this be done more easily using TeX
> itself, i.e.:
>
> ----
> \documentclass[12pt]{article}
>
> \newcommand{\ProbEasyIntegral}{%
> Find the integral of $f(x)=x^2$ from $x=0$ to $x=10$.
> }

Here's how I would tackle this kind of task.

Firstly, create a LaTeX database file, organised
such as follows:

%%%%%%%  start of file  MathProblemsDatabase.tex  %%%%%%%%%

\newcommand{\showQuestion}[5]{%
\typeout{Question #1:#2  \string#3\empty}}%
\expandafter\ifx\csname processQuestion\endcsname\relax
\let\processQuestion\showQuestion
\fi

\processQuestion{trig}{1}{\EasyTrigQuestion}%
{ .... text of an easy Trigonometry question ...}
{ ....  text of solution to this question ....}

\processQuestion{trig}{2}{\HarderTrigQuestion}%
{ .... text of an slightly harder Trigonometry question ...}
{ ....  text of solution to this question ....}

...
...

\processQuestion{trig}{6}{\VeryHardTrigQuestion}%
{ .... text of a very hard Trigonometry question ...}
{ ....  text of solution to this question ....}

...
...  more questions on other topics, etc...
...

%%%%%%%%   end of file  MathProblemsDatabase.tex  %%%%%%%%

In such a file, each question is accompanied by

a.  2 pieces of data which are used to classify the
kind of question;  e.g.  'trig' for the type,
and a sequence number within that type;

b.  a control-sequence with a catchy name that can be
used to refer to this question;
e.g.  \EasyTrigQuestion , \HardTrigQuestion, etc.

c.  the text of the question

d.  separate text for a solution  (optional)

and most importantly:

e.  a "tag" control-sequence  \processQuestion
which need not have a formal definition yet.

The main idea is that \processQuestion marks the following
groups of data (5 such, in this example) as having some
relation to each other.

There are some lines of TeX and LaTeX coding at the top
of the file which define a "method" \showQuestion
which takes 5 arguments. It doesn't do much, except to
write some info into the .log file.
By including the line
\let\processQuestion\showQuestion
then the above file can be read without error by LaTeX
and produce a listing of the questions contained in the
file, along with their "catchy" control-sequence names.

Now here's the important part.

You can define other macros or "methods",
taking 5 parameters, to do various things with the data.

e.g. 1.


now the code-lines:
\let\processQuestion\aliasQuestion
\input MathProblemsDatabase.tex

would read the data, and make the appropriate
\newcommand definitions for each of the "catchy" names.

This might be appropriate in the preamble of a LaTeX job.
After using this, you could select questions by just
using the "catchy" macro-names for the ones that you want.

e.g. 2

\newcommand{\typesetQuestion}[5]{%
\begin{question}#4\end{question}
\begin{solution}#5\end{solution}}

now the code-lines, within a document body:

\let\processQuestion\typesetQuestion
\input MathProblemsDatabase.tex

would read the file and include typeset versions
of the questions and solutions within a LaTeX job,
using formatting defined by
\newenvironment{question} ....
\newenvironment{solution} ....
which have presumably been setup elsewhere.

Get the idea ?

By using   \let\processQuestion\...some-method-name...
you can specify what you want done with all the data
in the file, as the file is read.

OK, so how do we select specific records to work with,
omitting all the rest?

This requires 2 things:

a.  something that says which questions to use;
b.  defining suitable methods which use the result of a.

One way to do this was shown in "e.g. 1" above, using
the "catchy" macro-names in the body of a document.

It may actually be more convenient to specify the chosen
questions in the preamble, and use a fixed document-body
to produce the typeset questions themselves.

Here is one way to handle this strategy:

e.g.  for a. we can have a separate file with commands
such as:

\chooseQuestion{trig}{1}
\chooseQuestion{algebra}{3}
\chooseQuestion{integral}{2}
\chooseQuestion{integral}{4}
...
...

with a simple definition such as:

\newcommand{\chooseQuestion}[2]{%
\expandafter\let\csname quest:#1-#2\endcsname\empty}

Now consider the effect of a "method" such as:

\newcommand{\selectQuestion}[5]{%
\expandafter\ifx\csname quest:#1-#2\endcsname\empty
\typeout{Selected question: #1-#2}%
\begin{question}#4\end{question}%
\begin{solution}#5\end{solution}%
\else
\typeout{Ignoring question: #1-#2}%
\fi
}

With this, the coding:
\let\processQuestion\selectQuestion
\input MathProblemsDatabase.tex

will run through the database, finding all
the questions that were previously indicated
by a  \chooseQuestion{...}{...}  line.
For each question in the database, it writes
a message saying what was done: included or ignored.

If you are going to use this kind of thing a lot,
then it would be worthwhile to build in some coding
for detecting errors in the database file.

The following coding uses essentially all of the
ideas mentioned above, plus a few more.

\newcommand{\aliasQuestion}[5]{%
\expandafter\ifx\csname quest:#1-#2\endcsname\relax
\expandafter\newcommand\expandafter{%
\csname quest:#1-#2\endcsname}{#4}}%
\ifx\relax#3\relax\questMissingAlias{#1}{#2}%
\else\ifcat#3\active\relax
\ifx#3\unDeFinEd\relax
\expandafter\let\expandafter#3\csname quest:#1-#2\endcsname
\else\questDuplicateAlias{#1}{#2}{#3}\fi
\else\questIncorrectAlias{#1}{#2}{#3}\fi
\fi % end of \ifx
\else\questDuplicateName{#1}{#2}\fi
}
\newcommand{\questDuplicateName}[2]{%
\newcommand{\questDuplicateAlias}[1]{%
\typeout{**Warning: alias \string#3 for quest#1-#2 has already been
used!**}}
\newcommand{\questIncorrectAlias}[3]{%
\typeout{**Warning: alias \string#3 for quest#1-#2 is not a
macro-name!**}}
\newcommand{\questMissingAlias}[2]{%
\typeout{**Warning: no alias provided for quest#1-#2 **}}

... with \chooseQuestion  altered for checking purposes:

\newcommand{\chooseQuestion}[2]{%
\expandafter\ifx\csname quest:#1-#2\endcsname\relax
\questMissingQuest{#1}{#2}%
\else\expandafter\let\csname quest:#1-#2\endcsname\empty\fi
}
\newcommand{\questMissingQuest}[2]{%
\typeout{**Warning: no question #1-#2 is available! **}}

... and with a more sophisticated \selectQuestion :

\newcommand{\selectQuestion}[5]{%
\expandafter\ifx\csname quest:#1-#2\endcsname\relax
\questMissingQuest{#1}{#2}%
\else\expandafter\ifx\csname quest:#1-#2\endcsname\empty
\typeout{Selected question: #1-#2}%
\questHandleQuestion{#1}{#2}{#4}{#5}%
\else
\typeout{Ignoring question: #1-#2}%
\fi\fi
}
\newcommand{\questHandleQuestion}[4]{%
\begin{question}\label{quest:#1-#2}#3\end{question}%
\begin{solution}\label{soln:#1-#2}#4\end{solution}}

Now the LaTeX document can contain coding such as:

\newenvironment{question}{....}{.....}
\newenvironment{solution}{....}{.....}
% better yet, use  \newtheorem  and counters!

\let\processQuestion\aliasQuestion
\input MathProblemsDatabase.tex

% Alternatively, read these from an \input file:
\chooseQuestion{trig}{1}
\chooseQuestion{algebra}{3}
\chooseQuestion{integral}{2}
\chooseQuestion{integral}{4}
...
...

\begin{document}
....

\let\processQuestion\selectQuestion
\input MathProblemsDatabase.tex

....

Now the file  MathProblemsDatabase.tex  gets read twice.
Firstly, in the preamble, the in the body of the document
to get the actual questions and solutions.

Furthermore, the aliases ("chatty" macros) are defined
to give the text of specific questions, should this be
wanted --- e.g. reading the file for questions imposes
the order in which they appear in that file, and this
may not be suitable.

Sorry for the long posting.
Hopefully you'll find it useful.
(I'm reasonably confident that the coding is error-free.
If you have difficulties using it, let me know,
and include a URL for you database file, for testing.)

Hope this helps,

Ross

>
> \begin{document}
>
> \begin{enumerate}
>
> \item \ProbEasyIntegral
>
> \end{enumerate}
>
> \end{document}
>
> ----
>
> All the problem definitions could live in one file, to be included. One
> could get fancier and define a "Problem" environment (if using LaTeX),
> which took as an argument the name of the problem to be included, I
> think.
> I'd have to think about how to get TeX to do that.
>
> --
> Chris Goedde
> -----------------------------------------------------
> Please see <http://www.esm.psu.edu/mac-tex/> for list
> guidelines, information, and LaTeX/TeX resources.
>
>
>
------------------------------------------------------------------------
Ross Moore                                         ross at maths.mq.edu.au
Mathematics Department                             office: E7A-419
Macquarie University                               tel: +61 +2 9850 8955
Sydney, Australia                                  fax: +61 +2 9850 8114
------------------------------------------------------------------------

-----------------------------------------------------