Speaking TeXnically

n  Text of Talks on Macro Writing

n  Macro Writing Tips

n  Some Useful Macros


 

Text of Talks on Macro Writing

Real Life LaTeX:
Adventures of a TeX Consultant

and
Slides for `Real Life LaTeX' talk
Text and slides for talk given at TeX Users Group Northeast, NYC, March 1998, includes some code examples.

Getting TeXnical
From the archives, but intrepid macro writers may find it interesting: Talk on macro writing, TUG 1990


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