Monday, April 5, 2010

Default units

In the previous post, I mentioned that when changing font sizes, there is a neat hack that allows the font size macros to have default units. That is the subject of today's brief post. The setup is you want to devise a macro that sets a dimension register to a particular value. For example,
\newdimen\foo
\newcommand*\set[1]{\foo#1\relax}
Now if you know that most of the time the units used are in points—as is the case with the font size macros—you can add the units in the \set macro,
\newcommand*\set[1]{\foo#1 pt\relax}
This works unless you want to sometimes specify your own units. At this point, we can use the \afterassignment primitive and a macro with a delimited argument to scoop up the default units. This is exactly what the \@defaultunits macro does.
\def\@defaultunits{\afterassignment\remove@to@nnil}
\def\remove@to@nill#1\@nnil{}
We can change our \set macro to be
\newcommand*\set[1]{\@defaultunits\foo#1 pt\relax\@nnil}
Let's take a look to see what this does in two cases.
\set{10}
\set{10ex}
In the first case, \set expands which causes \@defaultunits to expand and the \afterassignment is set to \remove@to@nnil. Next, \foo 10 pt\relax causes the dimension register specified by \foo to be set to 10pt and now \remove@to@nnil expands which gobbles up the \@nnil and \set is finished.

In the second case, \@defaultunits expands and \afterassignment is set as before. This time, \foo 10ex causes the dimension register to be set to 10ex and \remove@to@nnil expands which gobbles the pt\relax\@nnil and \set is finished. The \relax is more crucial if the register being set is a skip register rather than a dimension register since the pt by itself is not sufficient for the assignment but the \relax causes TeX to stop looking for more skip specification tokens. Less brief than I intended.

No comments:

Post a Comment