Consider the following MWE. If I pass some TeX code to Lua (via \directlua) and Lua tries to pass it back to TeX (via tex.sprint), the following problem becomes apparent.
The code below prints
text is \newcommand {\foo }{##1} \foo end
As you can see, the # doubles once passed to Lua, and of course this breaks the macro \foo.
It's necessary to wrap the text argument in \detokenize or similar, in order to stop TeX expanding it before passing to to Lua, but both \detokenize and \unexpanded have this issue.
This question: Macro char # doubles when made letter? is probably the same phenomenon. And also How do I expand exactly once a macro which takes an argument.
Suggestions on how to work around this would be appreciated. I'd obviously prefer an approach whereby I wrap the argument passed to luafun inside \NewDocumentCommand in something, rather than adding extra special code to every occurence of # in my text.
And in this context, are there any other unpleasant surprises lurking in the wings with other special TeX characters? If so, please warn me now.
\documentclass[12pt]{article}
\usepackage{xparse}
\usepackage{filecontents}
\begin{filecontents*}{fn.lua}
function luafun (text)
texio.write_nl(string.format([[text is %s end]], text))
tex.sprint(text)
end
\end{filecontents*}
\directlua{local scratch = require "fn.lua"}
\NewDocumentCommand{\luafun}{+m}
{
\directlua{luafun([[\detokenize{#1}]])}
%\directlua{luafun([[\unexpanded{#1}]])}
}
\begin{document}
\luafun
{
\newcommand{\foo}[1]{#1}
%\foo{foo}
}
\end{document}
\directlua{luafun("\luaescapestring{\unexpanded{#1}}")}. Everything else will suffer from things like the hash doubling problem. – Henri Menke Jun 28 '19 at 06:42