49

Lua code environment

I moved on to XeTeX (XeLaTeX) a while ago. I was using pdfLaTeX before that, but now I'm quite comfortable with XeLaTeX.

Now, I'd like to use LuaLaTeX to embed Lua in some LaTeX documents. The doc states several ways to embed Lua in TeX, but they confuse me more than actually explain what I need to know about embedding Lua.

There's \directlua{ ... }, \luacode ... \endluacode, and \begin{luacode} ... \end{luacode} with the luacode package. The dots (...) is where Lua code would go.

Now, which one should I use?

And is there a quicker way to enter Lua environment like with math mode where I can enter mathmode with '$'?

Saving variables

A quick one: When using Lua code embedded in LuaLaTeX, all variables are lost when the code finishes. Now, can I save return values, etc. so I can use them in my document later, with \myvar for sinstance, or something?

1 Answer 1

62

There are two questions here. You should consider asking one question at a time for your next posts.

Now to the Lua code environment. Don't use any of them if you can. Just do

\directlua{  require("myfile")  }

and put all of your Lua code in that file. See another answer for a list of directories TeX searches for the file myfile.lua.

If for some reason you can't do that (when you are only allowed to ship only one file for example) you should use the environment luacode* (with *) from the luacode package. That has the safest character catcodes. That means you can say something like:

\begin{luacode*}
texio.write_nl("This is a string with\n a newline in it")
tex.print(-2, string.format( "5 %% 4 is %d ", 5 % 4))
\end{luacode*}

(You need the -2 as the first argument to tex.sprint(), because the % sign (resulting from the double %% is interpreted from TeX as a comment sign after the environment closes. TeX sees at the end of the environment 5 % 4 is 1 and treats the % as the end of input. So you need to tell TeX that this % is a regular character. You have two choices: either pass TeX a string like this: string.format("5 \\%% 4 is ...") so that TeX sees 5 \% 4 is ... as you would do with normal text or make % a normal letter, so TeX does not recognize it as a comment sign. To do that you have to change the category code. The easiest way is to assign the special catcode table -2 to tex.print(). It is a safe catcode table, no characters have a special meaning.)

If you need to use TeX macros in Lua code, use the luacode environment (without *):

\begin{luacode}
    local current_page = tonumber(\thepage)
    texio.write_nl("We are on page " .. current_page)
\end{luacode}

And if you need to put your code in a command, use \luaexec:

\newcommand\myrepeat[2]{%
\luaexec{
  for i=1,#1 do
     tex.sprint("\luatexluaescapestring{#2}")
   end
 }}

\myrepeat{4}{Hello world}

(you can't use the environments directly in a \newcommand, but you could use \luacodestar ... \endluacodestar if you really want the environment functionality). The \luatexluaescapestring{} is necessary to escape input characters like " that would be harmful to the Lua string.

You have also asked if there is a shortcut such as the $...$ for math typesetting. No, there is none. IMO that is not such a big problem, as Lua code (in practice, but YMMV) is only used at a few points (with macros or with environments for example) and not so much in running text. Mostly in packages. (See the documentation to the luacolor package for example. Even if you don't understand the package in full detail at the first glance, you can see where the TeX code is with the \directlua calls, aliased in the example to \LuaCol@directlua and how the Lua code is separated from it in another file. See that there are only very few lines of Lua code inside the \LuaCol@directlua commands? In my opinion we can learn a lot from this code, as Heiko Oberdiek is an excellent package writer.)

Now to your second question about Saving variables. If you don't declare your variables local, they are accessible in all Lua chunks. But you are asking to pass Lua code to TeX. You can do this for example:

\begin{luacode*}
tex.sprint("\setcounter{mycounter}{" .. my_lua_value .. "}")
\end{luacode*}

to create a \setcounter command with your value. Or you can use the tex.count Lua interface:

\begin{luacode*}
tex.count[10] = my_lua_value
\end{luacode*}

and your value is in \count10. But this is a bit dangerous as you have to be certain to use a free counter.

7
  • Thanks for clarifying. When defining a command, couldn't I use \directlua{} just as well? Or is there a significant difference with \luaexec{}?
    – polemon
    Oct 30, 2011 at 18:50
  • 1
    @polemon You can use \directlua{} instead. But all kinds of characters will spoil your experience: %, \ , --, \\ and ~. You have to be careful and escape them. I strongly suggest to define a function in a separate lua file and call that function from your \directlua{} or \luaexec{} command. Then you don't have to worry about TeX interpreting some funny characters even before Lua gets to see them.
    – topskip
    Oct 30, 2011 at 19:05
  • Your example with \repeat{4}{Hello world\par} does not work here with LuaTeX from MiKTeX 2.9. I get the error message { for i=1,4 do tex.sprint("\luatexluaescapestring {Hello world ! Paragraph ended before \luaexec was complete. <to be read again> \par l.28 \repeat{4}{Hello world\par} It works nicely without \par though, is this somehow not allowed in this command?
    – Alexander
    Aug 25, 2012 at 12:22
  • @Alexander thanks for the pointer. My example was broken. I can't really tell why it failed due to lack of internal insight.
    – topskip
    Aug 25, 2012 at 13:04
  • 1
    @MartinSchröder have you tried tex.tprint()? Without looking at the manual, I guess the following could do: tex.tprint({"\\"},{-2,"foo@bar"}). But IIRC -2 changes the catcodes to 'other' which doesn't help with command names. Perhaps surround this with \makeat...?
    – topskip
    Sep 13, 2012 at 17:56

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .