Macro Writing Tips
Is there some aspect of macro writing that has
been mystifying you?
Email your question to
info@TeXnology.com
and the response may appear
on this page in the future.
Some misleading error messages
Here are some small tips that might
help when debugging your macro set.
Suppose you were writing a set of macros and
got this error message when attempting to
run a test:
! Illegal parameter number in definition of \abc.
to be read again
1
test.tex(5) : \def\xyz#1
{}
?
You find this message mysterious because \abc
wasn't using any parameter numbers. The answer
is that your definition of \abc is missing
an ending curly bracket, and the error was
caused by the presumed definition of \abc
included the definition of \xyz which occurred
later in the macro file.
If one were to write:
\let\xyz=\zzz
\def\zzz{Hi there}
and then type
\xyz
You would get this error message:
! Undefined control sequence.
\xyz
Why? You've
\let\xyz=\zzz and
\zzz
is defined...
Answer: When you use \let it takes
the current state of the macro it has
been \let equal to; in this case
\zzz
has not yet been defined
so you have \let\xyz= to undefined; thus
the mysterious error message.
If instead one were to define \zzz first;
\def\zzz{Hi there}
\let\xyz=\zzz
and then type
\xyz
You would have `Hi there' appear
as you originally expected.
If you had written:
\newif\ifsomething
\ifsomething \ifsomething\fi
This error message might give you pause
for thought
! Incomplete \iffalse; all text was
ignored after line 7.
(inserted text)
\fi
It is caused by a missing \fi, so you
know that if you get this error message you
must look for a badly nested set of
\ifs and \fis
And a Tip:
Here is a way to compare
output routines, so that you can
test to see what output routine
is active at a particular point
in your document:
\def\xfirstcolout{{\firstcolout }}
\xdef\curroutput{\the\output}
\ifx\curroutput\xfirstcolout
\typeout{^^J^^J SEES FIRST ^^J^^J}\fi
This will give you the message SEES FIRST
to let you know that the firstcolout output
routine is in effect at the point where
the comparison is made.
|
Some Useful Macros: Bolding Math, Lettered Equations,
Turning Footnotes into Endnotes
Bolding Math
There are some math characters that don't get
bold even though they are found in the
argument of \mathbf.
In this example, \omega
and
+
will not turn bold:
\[\mathbf{\Psi,\omega +}\]
This definition will allow you to turn \omega
and
other math character bold:
\def\bsymbol#1{\mbox{\boldmath
$\displaystyle#1$\unboldmath}}
Now try this:
\[ \mathbf{\Psi,\bsymbol{\omega +}} \]
and you will see that the omega and + are now bold.
If you wanted to use this command in subscripts
and superscripts as well as display math, a
little more fanciness would be required, but
\bsymbol{} demonstrates the principle.
Lettered Equations
One can go to a great deal of trouble to automate
lettered equations, but here is a simple method
that works quite adequately:
In the body of the equation, you may temporarily
change the definition of \theequation, the equation numbering macro.
The new definition will be confined to the particular
equation where you have written it.
\begin{equation}
\alpha\beta\Gamma\Delta
\def\theequation{21a}
\end{equation}
and for the next lettered equation, you
can do the same thing:
\begin{equation}
1234\Delta
\def\theequation{21b}
\end{equation}
When you are ready to return to normal equation numbering
you may set the new equation number, remembering to
set it to one less than the number you actually want,
since the equation macro will advance the counter by 1.
In this case we set the equation number to `21' so
that the next equation will be `22'.
\setcounter{equation}{21}
You will find that you can do the same thing in
the body of an eqnarray.
Turning Footnotes into Endnotes
Dynamically making definitions for each endnote using
\csname ...\endcsname with an internal counter allows
us to use those definitions, one by one, at the end
of the chapter or article, when we run a \loop which
increments a counter and calls for each definition.
This technique, making definitions containing a counter,
and then calling for a series of definitions with a loop
may be used in many other LaTeX macros applications as well.
Make counters:
\newcount\footnum
\newcount\savefootnum
Make definition of endnote:
\long\def\endnote#1{%
% Get endnote number,
% raise it as if it were a footnote number.
\global\advance\footnum by 1\relax$^{\the\footnum}$
% Make definition of foot1, foot2, etc., to be
used
% when endnotes are printed:
\long\expandafter%
\gdef\csname foot\the\footnum\endcsname{%
\vbox{\footnotesize
\noindent\hbox to10pt{\the\footnum.\hfill}
#1\strut\vskip1sp}%
\vskip1pt}% <== end of foot1, etc., definition
}% <== end of endnote definition
Set footnote to be equal to endnote so that
when user types \footnote, he/she actually
gets \endnote.
\let\footnote\endnote
Print endnotes with \notes command.
\def\notes{{\ifnum\footnum=0\else%
% Test to see if there are any endnotes
\savefootnum=\footnum% save the number of endnotes
\footnum=0
\section*{Notes}%
% Test to see if we've used all the endnotes
\noindent\loop\ifnum\savefootnum>\footnum
\global\advance\footnum by1\relax%
\csname foot\the\footnum\endcsname\relax
% Print the definition of this endnote
\repeat\global\footnum=0\relax\fi}}
Used:
Testing endnotes
here,
\footnote{This is the first footnote.} and
here is another.
\footnote{This is the second one.}
\notes
|