7

I have a Lua function that generates LaTeX content (a string containing LaTeX commands like "\\textbf{foo}") and it can be successfully outputted with \lua_now:n and tex.print(). Now I'm planning to record the content for the purpose of l3build regression test and I try to pass the content to a token list and then write it the log file with \tl_show:N. However the following code raises an error: Illegal parameter number in definition of \l__csl_bibliography_tl. Is there another approach?

\documentclass{article}
\usepackage{luacode}
\begin{luacode*}
function make_bibliography()
  local result = "\\textbf{Foo}"
  tex.print(result)
end
\end{luacode*}

\ExplSyntaxOn \tl_new:N \l__csl_bibliography_tl \cs_new:Npn \printbibliography { % \lua_now:n { make_bibliography() } % It works fine. \tl_set:Nx \l__csl_bibliography_tl { \lua_now:n { make_bibliography() } } \tl_show:N \l__csl_bibliography_tl \tl_use:N \l__csl_bibliography_tl } \ExplSyntaxOff

\begin{document} \printbibliography \end{document}

2 Answers2

9

You can set the tl (macro) from Lua:

\documentclass{article}
\usepackage{luacode}
\begin{luacode*}
function make_bibliography()
  local result = "\\textbf{Foo}"
  token.set_macro("l__csl_bibliography_tl",result)
end
\end{luacode*}

\ExplSyntaxOn \tl_new:N \l__csl_bibliography_tl \cs_new:Npn \printbibliography { \lua_now:n{ make_bibliography() } \tl_show:N \l__csl_bibliography_tl \tl_use:N \l__csl_bibliography_tl } \ExplSyntaxOff

\begin{document} \printbibliography \end{document}

Note that token.set_macro does not handle the case where result contains e.g. a ~ character and the catcode of ~ is currently active.

Also any control sequences used (eg \textbf here) must already be in the hash table. See tilde ~ in lua adds a new line for some discussion of this.

David Carlisle
  • 757,742
5

The problem is that \textbf doesn't survive x-expansion. You can wrap the problematic construction with \text_expand:n:

\documentclass{article}
\usepackage{luacode}

\begin{luacode} function make_bibliography() local result = "\textbf{Foo}" tex.print(result) end \end{luacode}

\ExplSyntaxOn \tl_new:N \l__csl_bibliography_tl \cs_new:Npn \printbibliography { \tl_set:Nx \l__csl_bibliography_tl { \text_expand:n { \lua_now:n { make_bibliography() } } } \tl_show:N \l__csl_bibliography_tl \tl_use:N \l__csl_bibliography_tl } \ExplSyntaxOff

\begin{document}

\printbibliography

\end{document}

In the console you'll see

> \l__csl_bibliography_tl=\textbf {Foo}.

and the output is

enter image description here

egreg
  • 1,121,712
  • I think Carlisle's approach is simpler because it involves less expansion control. Thank you all the same. – Zeping Lee Sep 22 '22 at 16:00
  • @ZepingLee But it assumes that token lists variables are implemented as macros (which is true up to some point). – egreg Sep 22 '22 at 16:07