0

I have the following external lua script:

-- file mylua.lua
function test(input)
   tex.sprint(input)
end

And the following lualatex document:

\documentclass{article}
\usepackage{luacode}
\directlua{dofile("mylua.lua")}

\begin{document}

This works: \directlua{test("Hello world!")}

But this doesn't: \directlua{test("\textit{Hello world!}")} \end{document}

This is a simple example illustrating an error I get in a more complex code I'm writing. I moved my lua code to an external file, in order to avoid problems escaping characters. However, inevitably I have to use macros in my \directlua calls, and most of the times I cannot control what the macros are.

Is there any way of avoiding this problem?

NVaughan
  • 8,175

1 Answers1

4

You want to print the Lua string "\textit..." but \t is a tab character so you need "\\textit...." in the Lua but \directlua expands its argument like \edef so you need to stop \\ expanding so:

\documentclass{article}
\usepackage{luacode}
\directlua{dofile("mylua.lua")}

\begin{document}

This works: \directlua{test("Hello world!")}

But this doesn't: \directlua{test("\string\textit{Hello world!}")} \end{document}

You could also use

\directlua{test("\luaescapestring{\detokenize{\textit{Hello world!}}}")}

which may be better if you don't have easy control over the content.

enter image description here

You have loaded (but not used) the luacode package which offers some wrappers around \directlua but I find it simpler usually not to use them and control the expansion directly.

David Carlisle
  • 757,742
  • Thanks. But as I said, I don't have control as to the argument of test(), so I cannot manually add \string\ every time I need it. – NVaughan Jul 31 '20 at 23:15
  • you can use \detokenize{...} around the whole thing and use \luaescapestring{...} to automatically double \ and other needed Lua escapings, I just thought it more useful to do it by hand here to highlight what the issue is. Or you could use the luacode package functions. – David Carlisle Jul 31 '20 at 23:38
  • @NVaughan see update – David Carlisle Jul 31 '20 at 23:48
  • Thanks. That did it. – NVaughan Jul 31 '20 at 23:55
  • 1
    Since the OP loads the luacode package, you could make use of the package's \luastringN macro to accomplish what "\luaescapestring{\detokenize{...}}" does. – Mico Aug 01 '20 at 00:09
  • @DavidCarlisle The common idiom is \luaescapestring{\unexpanded{...}} (see also https://tex.stackexchange.com/questions/550673). Using \detokenize might be a bad idea because this will add spaces, e.g. \textit{Hello} becomes \textit {Hello}. If the string is written back to TeX with the default catcode table, that is not a problem but if the string is processed in Lua this might lead to some confusion. – Henri Menke Aug 01 '20 at 04:19
  • @HenriMenke \directlua{print("\luaescapestring{\detokenize{\relax\relax{z}}}")} and \directlua{print("\luaescapestring{\unexpanded{\relax\relax{z}}}")} both have spaces after the \relax so there are some differences but it isn't clear that one is always better than the other, generally \unexpanded is like having \noexpand on every token (which adds spaces when the tokens are written out) and \detokenize is like having \string on every token (which does not add spaces) – David Carlisle Aug 01 '20 at 09:20