TeX Macros Defining Other Macros

Lately I have been writing a script using TeX and the screenplay package by John Pate. I want to share a simple example of how I wrote a macro that itself defines a macro. Honestly this article is more for my own future reference, because I found this task to be a bit non-intuitive.

The Goal

The screenplay package has a \dialog macro which you use like so:

\dialog{Violet} Here's where the monologue would go.

In other words: \dialog{Character} Content. I found myself creating macros for common characters, e.g.

\def\Violet#1{\dialog{Violet} #1}

\Violet Here's where the monologue would go.

But repeating that macro definition for every major character gave me that programmer’s sense of dread about repeating oneself. What I decided to do was create a macro that would define the macro above for me. That way I could write:

\newcharacter{Violet}
\Violet Here's where the monologue would go.

So here’s how I did it.

The Obvious First Attempt

This was the simplest definition I could think of:

\def\newcharacter#1{\def\#1##1{\dialog{#1} ##1}}

% Now hopefully...

\newcharacter{Violet}

% ...would expand into...

\def\Violet#1{\dialog{Violet} #1}

This fails though. This version \newcharacter macro chokes when it comes to creating the desired \Violet macro name. To fix this problem we have to make sure TeX treats the argument to \newcharacter as a ‘control sequence’.

Enter \csname

Writing \def\#1 looks like it would create a control sequence, but it doesn’t. TeX provides the \csname and \endcsname macros for this purpose. Everything that appears between the two macros is expanded like normal and leaves you with a control sequence. For example:

\csname foo \endcsname    % Expands into \foo

Notice how \csname takes care to add the \ for the name. With that in mind I then tried this:

\def\newcharacter#1{\def\csname #1\endcsname##1{\dialog{#1} ##1}}

But this fails too. What the Hell? Shouldn’t \newcharacter{Violet} expand into \def\Violet…? Well here’s the problem: TeX is expanding the tokens in the order they appear. Since the \def comes first that’s what it starts with. So we need a way to delay that expansion.

\expandafter Saves the Day

This macro is simple to understand:

\expandafter\foo\bar

This reverses the order of expansion so that TeX will expand \bar first, leaving us with \foo followed by whatever is the result of expanding \bar. This helps define the \newcharacter macro because it provides a way to expand the control sequence name, i.e. the \csname part, while leaving the preceeding \def intact. Thus:

\def\newcharacter#1{\expandafter\gdef\csname #1\endcsname##1{\dialog{#1} ##1}}

(Note: The ##1 you see becomes #1 after expansion, which is how the resulting macro definition accepts an argument.)

Now the macro works, i.e.

\newcharacter{Violet}
\Violet Here's where the monologue would go.

The macro \gdef is the same as \global\def, and honestly I don’t know if it is necessary but it felt like the right thing to use here. In any case, the important thing is that \expandafter reaches over \gdef and expands everything between \csname and \endcsname. This takes the argument to \newcharacter, creates a control sequence name from that argument, and leaves us with \gdef\Violet (or whatever name we give to \newcharacter). The expansion works like so:

\def\newcharacter#1{\expandafter\gdef\csname #1\endcsname##1{\dialog{#1} ##1}}

\newcharacter{Violet}

% The above expands into this (note how #1 appears in the output because
% we 'escape' it in the \newcharacter definition):

\def\Violet#1{\dialog{Violet} #1}

% Now we can finally write this:

\Violet Here's where the monologue would go.

Conclusion

What I learned from this experience is that controlling expansion is a tricky aspect of writing macros which define other macros. The book “TeX By Topic” by Victor Eijkhout proved to be an invaluable tool in solving this little puzzle, and continues to be an ever-rewarding reference as I learn more about the inner details of TeX. If you’re an experience TeX user and found this article too simplistic then I would still recommend Eijkhout’s book, as it covers so much of TeX in great detail with fantastic examples.

Advertisements

2 thoughts on “TeX Macros Defining Other Macros

  1. Thanks for the kind words about my book.

    Since you mention screenplays, in some old issue of Tugboat I wrote some macros of un-orthodox paragraph shapes (https://www.tug.org/TUGboat/tb11-1/tb27eijkhout.pdf). One of them is for typesetting Shakespeare plays: sometimes a character does not utter a full iambic pentameter, so you want to typeset the next character’s opening words to start offset to indicate their place in the meter. (Bother, that sounds very complicated. Better give an example:

    J: Romeo!
    R:…………. My dear!
    J:………………………….At what o’clock tomorrow

    Victor.

Add Your Thoughts

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s