Changes

Jump to navigation Jump to search
m
luaTeX -> LuaTeX
{{note | This is a wikified version of [https://www.tug.org/members/TUGboat/tb30-2/tb95mahajan-luatex.pdf this TugBoat article ]. Feel free to modify it. }}
In this article, I explain how to use lua to write macros in [[LuaTeX]]. I give some examples of macros that are complicated in [[PdfTeX]], but can be defined easily using lua in luaTeXLuaTeX. These examples include macros that do arithmetic on their arguments, use loops, parse their arguments, and manipulate verbatim text.
= Introduction =
</texcode>
The <tt>pgfmath</tt> library implements the macro in a similar way, but limits the number of shifts that it does. These macros highlight the state of affairs in writing TeX macros. Even simple things like multiplying two numbers are hard; you either have to work extremely hard to circumvent the programming limitations of TeX, or, more frequently, hope that someone else has done the hard work for you. In luaTeXLuaTeX, such a function can be written using the <code>/</code> operator (I will explain the details later):
<texcode>
\def\DIVIDE#1#2{\directlua{tex.print(#1/#2)}}
</texcode>
Thus, with luaTeX LuaTeX ordinary users can write simple macros; and, perhaps more importantly, can read and understand macros written by TeX wizards.
Since the luaTeX LuaTeX project started it has been actively supported by ConTeXt. <ref>Not surprising, as two of luaTeX's LuaTeX main developers&mdash;Taco Hoekwater and Hans Hagen&mdash;are also the main ConTeXt developers.</ref> These days, the various <em>How do I write such a macro</em> questions on the ConTeXt mailing list are answered by a solution that uses lua. I present a few such examples in this article. I have deliberately avoided examples about [[Fonts in LuaTeX | fonts]] and non-Latin languages. There is already quite a bit of documentation about them. In this article, I highlight how to use luaTeX LuaTeX to write macros that require some <em>flow control</em>: randomized outputs, loops, and parsing.
= Interaction between TeX and lua =
To a first approximation, the interaction between TeX and lua is straightforward. When TeX (i.e., the luaTeX LuaTeX engine) starts, it loads the input file in memory and processes it token by token. When TeX encounters <code>\directlua</code>, it stops reading the file in memory, <em>fully expands the argument of <code>\directlua</code></em>, and passes the control to a lua instance. The lua instance, which runs with a few preloaded libraries, processes the expanded arguments of <code>\directlua</code>. This lua instance has a special output stream which can be accessed using <code>tex.print(...)</code>. The function <code>tex.print(...)</code> is just like the lua function <code>print(...)</code> except that <code>tex.print(...)</code> prints to a <em>TeX stream</em> rather than to the standard output. When the lua instance finishes processing its input, it passes the contents of the <em>TeX stream</em> back to TeX.<ref>The output of <code>tex.print(...)</code> is buffered and not passed to TeX until the lua instance has stopped.</ref> TeX then inserts the contents of the <em>TeX stream</em> at the current location of the file that it was reading; expands the contents of the <em>TeX stream</em>; and continues. If TeX encounters another <code>\directlua</code>, the above process is repeated.
As an exercise, imagine what happens when the following input is processed by luaTeXLuaTeX. <ref>In this example, I used two different kinds of quotations to avoid escaping quotes. Escaping quotes inside <code>\directlua</code> is tricky. The above was a contrived example; if you ever need to escape quotes, you can use the <code>\startluacode ... \stopluacode</code> syntax explained later.</ref>
<texcode>
</texcode>
On top of these luaTeX LuaTeX primitives, ConTeXt provides a higher level interface. There are two ways to call lua from ConTeXt. The first is a macro <code>\ctxlua</code> (read as ConTeXt lua), which is similar to <code>\directlua</code>. (Aside: It is possible to run the lua instance under different name spaces. <code>\ctxlua</code> is the default name space; other name spaces are explained later.) <code>\ctxlua</code> is good for calling small snippets of lua. The argument of <code>\ctxlua</code> is parsed under normal TeX catcodes (category codes), so the end of line character has the same catcode as a space. This can lead to surprises. For example, if you try to use a lua comment, everything after the comment gets ignored.
<texcode>
\ctxlua
</texcode>
I could have written a wrapper so that the function takes a list of words and chooses a random word among them. For an example of such a conversion, see the <em>sorting a list of tokens</em> page on the [http://luatex.bluwiki.com/go/Sort_a_token_list luaTeX LuaTeX wiki]
In the above, I created a name space called <code>userdata</code> and defined the function <code>random</code> in that name space. Using a name space avoids clashes with the lua functions defined in luaTeX LuaTeX and ConTeXt.
In order to avoid name clashes, ConTeXt also defines independent name spaces of lua instances. They are
</texcode>
Since I defined the function <code>random</code> in the <code>user</code> instance of lua, I did not bother to use a separate name space for the function. The lua functions <code>os.time</code>, which is defined by a luaTeX LuaTeX library, and <code>context</code>, which is defined by ConTeXt, needed to be accessed through a <code>global</code> name space. On the other hand, the <code>math.randomseed</code> function, which is part of lua, could be accessed as is.
A separate lua instance also makes debugging slightly easier. With <code>\ctxlua</code> the error message starts with
Normally, it is best to define your lua functions in the <code>user</code> name space. If you are writing a module, then define your lua functions in the <code>third</code> instance and in a name space which is the name of your module. In this article, I will simply use the default lua instance, but take care to define all my lua functions in a <code>userdata</code> name space.
Now that we have some idea of how to work with luaTeXLuaTeX, let's look at some examples.
= Arithmetic without using a abacus =
We only needed to add three <code>\expandafter</code>s to make the naive loop work. Nevertheless, finding the right location of <code>\expandafter</code> can be frustrating, especially for a non-expert.
By contrast, in luaTeX LuaTeX writing loops is easy. Once a lua instance starts, TeX does not see anything until the lua instance exits. So, we can write the loop in lua, and simply print the values that we would have typed to the TeX stream. When the control is passed to TeX, TeX sees the input as if we had typed it by hand. Consequently, macro expansion is no longer an issue. For example, we can get the above table by:
<texcode>
\startluacode
This monstrosity is a typical TeX parser. Appropriate characters need to be made active; occasionally, <code>\lccode</code> and <code>\uccode</code> need to be set; signaling tricks are needed (for instance, checking if <code>\chemlowbox</code> is void); and then magic happens (or so it seems to a flabbergasted user). More sophisticated parsers involve creating finite state automata, which look even more monstrous.
With luaTeXLuaTeX, things are different. luaTeX LuaTeX includes a general parser based on PEG (parsing expression grammar) called [http://www.inf.puc-rio.br/roberto/lpeg/lpeg.html lpeg]. This makes writing parsers in TeX much more comprehensible. For example, the above <code>\molecule</code> macro can be written as
<texcode>
= Conclusion =
luaTeX LuaTeX is removing many TeX barriers: using system fonts, reading and writing Unicode files, typesetting non-Latin languages, among others. However, the biggest feature of luaTeX LuaTeX is the ability to use a high-level programming language to program TeX. This can potentially lower the learning curve for programming TeX.
In this article, I have mentioned only one aspect of programming TeX: macros that manipulate their input and output some text to the main TeX stream. Many other kinds of manipulations are possible: luaTeX LuaTeX provides access to TeX boxes, token lists, dimensions, glues, catcodes, direction parameters, math parameters, etc. The details can be found in the [http://www.luatex.org/documentation.html luaTeX LuaTeX manual].
= Notes =
<references />

Navigation menu