13

How to make the following code to compile?

\documentclass{article}

\newcommand*{\mycommand}{\directlua{for i = 1, 10 do tex.sprint(i\hskip1cm) end}}     %does not work
%\newcommand*{\mycommand}{\directlua{for i = 1, 10 do tex.sprint(i\\hskip1cm) end}}   %does not work
%\newcommand*{\mycommand}{\directlua{for i = 1, 10 do tex.sprint(i) end}}             %works 

\begin{document}
test \mycommand
\end{document}
13

First, you want to concatenate the value of the variable i with the token \hskip1cm, but the expression i\hskip1cm is not a valid lua expression. What you need is to make \hskip1cm a lua string and concatenate it with the value of i. That is:

tex.sprint(i .. "\hskip1cm")

This, however, won't work either because inside the quotes, the \ is a escape-char for lua, so \h will be interpreted as a escape sequence, and lua will complain that \h is an invalid escape sequence. So you have to "escape the escape":

tex.sprint(i .. "\\hskip1cm")

This would be ok for lua, but causes problems to TeX, since it makes \\ to appear inside a tex definition, and TeX tries to expand it, causing trouble.

You can avoid this trouble in two different ways:

First solution

This is the preferred one. Move your lua code to an external file. For example, create a file called mycommand.lua, which contains a lua function implementing your code:

-- mycommand.lua
function mycommand()
    for i = 1, 10 do
        tex.sprint(i .. "\\hskip1cm")
    end
end

Then, in your tex file, run the lua file (which defines that function and makes it available for lua), and define \mycommand to execute the function mycommand. This way:

\documentclass{article}
\directlua{dofile("mycommand.lua")}  % This defines the lua function mycommand()

\newcommand*{\mycommand}{\directlua{mycommand()}} % This defines the tex macro
\begin{document}
test \mycommand
\end{document}

Note that the expansion of \mycommand does not contain now any \\, so TeX is happy. When TeX expands \mycommand, this causes the function mycommand() to be executed, and this will "output" into the tex document the concatenation of i.."\\hskip1cm", which results into 1\hskip1cm2\hskip1cm3\hskip1cm etc, which is ok. The resulting pdf shows the intended result:

result

Second solution

This is uglier and in general not recommended. You can put any tex macro inside \luatexluaescapestring, and this will modify its expansion so that the result is a valid lua string. So, if you write for example "\luatexluaescapestring{\foo}" this will produce a complex string which contains the expansion of \foo, but wich each \ escaped as \\. Applying this to your example:

\documentclass{article}   
\newcommand*{\mycommand}{%
  \directlua{for i = 1, 10 do tex.sprint(i .. "\luatexluaescapestring{\hskip1cm}") end}
}
\begin{document}
test \mycommand
\end{document}

Note how you still require double quotes around it, to get a lua string which can be concatenated to the value of variable i.

  • 4
    If the package luacode is loaded, the turgid "\luatexluaescapestring{\hskip1cm}" may be replaced with the more concise \luastring{\hskip1cm}. – Mico Sep 19 '14 at 18:03
5

For solution 1 above, to avoid backslash escape, I suggest to use the bracket version of lua string (the number of = characters can be any number provided you use the same twice) :

-- mycommand.lua
function mycommand()
    for i = 1, 10 do
        tex.sprint(i .. [===[\hskip1cm]===])
    end
end

If someone with enough reputation can reply this to the answer, please do so.

  • 1
    Welcome to TeX.SE! I think this is a useful suggestion that's good enough to be an answer on its own. – ShreevatsaR Mar 16 '18 at 16:15
1

One can put all together in one file for small parts of lua code :

\documentclass{article}
\usepackage{luacode}

\begin{luacode}
    function mycommand()
        for i = 1, 10 do
            tex.sprint(i .. "\\hskip1cm")
        end
    end
\end{luacode}

\newcommand*{\mycommand}{\directlua{mycommand()}}

\begin{document}
test \mycommand
\end{document}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.