Escaping strings
When passing TeX tokens as Lua strings, characters that are special to Lua have to be escaped. A naive example of such an error would be
\newcommand\justprint[1]{\directlua{tex.sprint("#1")}}
\justprint{"hello"}
which results in the error
[\directlua]:1: ')' expected near 'hello'.
\justprint #1->\directlua {tex.sprint("#1")}
because #1 is formally replaced by "hello" which gives the invalid lua syntax tex.sprint(""hello""). This can be fixed easily be applying \luaescapestring.
\newcommand\justprint[1]{\directlua{tex.sprint("\luaescapestring{#1}")}}
\justprint{"hello"}
If the luacode package is loaded, one can replace \directlua{tex.sprint("\luaescapestring{#1}")}} with \directlua{tex.sprint(\luastring{#1})}}.
Printing numbers
Let's try to print the number 42 and the string foo into the document.
\directlua{tex.sprint(42, "foo")}
But only the string foo shows up, what happened?
The gotcha here is that tex.sprint takes a variable number of arguments and performs different things depending on their types. If there are several arguments and the first argument is a number, then it is interpreted as a category code table number and not printed into the document. Therefore it is always a good idea to just explicitly convert anything that you want to print into a string.
\directlua{tex.sprint(tostring(42), tostring("foo"))}
The second tostring is gratuitous in this situation, but you should always run tostring on function return values. Moreover, if you ever forget to convert an integer to a string, LuaTeX may silently do it for you, but beware that this undocumented feature (as of version 1.13) may be unsupported in the future.
You can also use the concatenation operator .. as soon as one operand is a string
\directlua{tex.sprint((42).."foo")}
Inhibiting expansion
The \directlua primitive fully expands its arguments which can cause errors if there is content present that is not expandable.
For example if we want to execute \section{Title},
\directlua{tex.sprint("\section{Title}")}
will not work because the \section command is executed too early. To solve this problem the following common idiom is used:
\directlua{tex.sprint("\luaescapestring{\unexpanded{\section{Title}}}")}
The \unexpanded primitive will inhibit expansion and \luaescapestring makes sure that the leading \s of \section is not interpreted as an escape sequence.
If the luacode package is loaded, one can replace tex.sprint("\luaescapestring{\unexpanded{\section{Title}}}") with tex.sprint(\luastringN{\section{Title}}).
Another straightforward possibility uses the \string primitive together with long lua strings:
\directlua{tex.sprint([[\string\section{Title}]])}
After \string, \section is no longer considered as a command, and long lua strings do not consider \ as a control character.
Typesetting the result, i.e, what's returned by a Lua function
When setting up LaTeX macros that contain \directlua statements to do something in real time, beginners may not be aware of the fact that simply “returning” the correct object to LaTeX's control does not suffice to get it typeset; an explicit tex.sprint directive is required as well. Take, for example,
\directlua{function modify ( s )
return ( s:gsub ( "Hello World" , "Hola Mundo" ) )
end
}
\newcommand\modify[1]{\directlua{modify("#1")}}
When typing How to say \modify{Hello World} in Spanish? the output will be “How to say[two blank spaces]in Spanish?”
To get the desired output, it's necessary to write, say, \newcommand\modify[1]{\directlua{tex.sprint(modify("#1"))}}.
Comments within \directlua
As already seen the argument of the \directlua is first managed according to TeX rules. In particular, % starts a TeX comment:
\directlua{tex.sprint("this is printed% but not this comment"
(up to the real closing quote)"
)}
is equivalent to
\directlua{tex.sprint("this is printed(up to the real closing quote)" )}
We observe that \directlua is fed with one single line of instructions. The consequence is that lua short comments apply to more instructions than expected:
\directlua{
tex.sprint("One"); -- One is printed
tex.sprint("Two"); -- but not Two
}
You can use long comments instead
\directlua{
tex.sprint("One"); --[[ One is printed ]]
tex.sprint("Two"); --[[ Two is printed as well ]]
}
or the luacode environment
\begin{luacode}
tex.sprint("One"); -- One is printed
tex.sprint("Two"); -- Two is print as well
\end{luacode}
Sharing data
lua can have read and write access to many TeX variables. For example next LaTeX code defines a counter, prints and modifies it from the lua side, then prints its updated value from the LaTeX side:
\newcounter{abc}
\setcounter{abc}{421}
\directlua{
tex.sprint(tostring(tex.getcount('c@abc')));
tex.setcount('c@abc', 666);
}
\arabic{abc}
The output is "421 666". This works as well for dimensions, boxes,... Chapter 10.3 of the LuaTeX manual is of great help on the subject.
For macros this is not as transparent. We can't see the category codes from the lua side because token.get_macro('foo') is the detokenized content of \foo. Nor can we define macros with parameters with token.set_macro, for that we must use tex.print. Nevertheless, macros can be used to share information between TeX and lua (see Chapter 10.6 of the LuaTeX manual). We will illustrate this below.
On the opposite, TeX does not have any direct access to lua variables.
One of the major differences between the TeX and the lua world is that lua variables do not obey the TeX grouping mechanism. For example, next LaTeX environment prints, when closed, the number of the line containing the \begin:
\newenvironment{Demo}{
\directlua{ begin_lineno = tex.inputlineno }
} {
\directlua{ tex.sprint(begin_lineno) }
}
This won't work as soon as we embed a Demo environment into another one because begin_lineno only takes into account the last \begin. Using LaTeX counters instead would solve the problem.
More generally, data that obey to TeX groups should be stored on the TeX side.
Jumping back and forth between TeX and Lua
\directlua allows to execute lua instructions from the TeX side whereas tex.sprint allows to execute TeX instructions from the lua side. We have seen how feeding \directlua may be tricky, now we see that printing is asynchronous, somehow
Within \directlua argument, the various tex.print functions give instructions to TeX. But these instructions are only executed at the end of \directlua: hereafter the content of the macro \foo is alternately "day" and "night",
\directlua{
token.set_macro('foo', 'day'); --[[ same as \string\def\string\foo{day} ]]
tex.sprint([[\string\foo]]);
token.set_macro('foo', 'night'); --[[ same as \string\def\string\foo{night} ]]
tex.sprint([[\string\foo]]);
}
The result is not "day night" as we may expect, it is "night night"! This is just like if all the print instructions were gathered at the very end:
\directlua{
token.set_macro('foo', 'day');
token.set_macro('foo', 'night');
tex.sprint([[\string\foo]]);
tex.sprint([[\string\foo]]);
}
and we see how the first line is absolutely useless. In order to obtain "day night", we would have to use two separate \directlua:
\directlua{
token.set_macro('foo', 'day');
tex.sprint([[\string\foo]]);
}
\directlua{
token.set_macro('foo', 'night');
tex.sprint([[\string\foo]]);
}
A corollary is that merging consecutive \directlua instructions is not always safe. Moreover, when the discussion between TeX and lua involves more complex instructions, some callback pattern may help:
\direclua{
<lua instructions>
tex.print(<tex instructions>)
function callback()
<to be performed after the tex instructions>
end
tex.print([[\string\directlua{callback()}]])
}
tex.runtoks or lua coroutines illustrated in this answer may help in that situation, but that is advanced usage.
A few unsorted things (need to be written out)
- finding libraries
- error reporting (line numbers might be within the
\directlua call)
- percent and other "funny" characters and luacode package