LuaLaTeX 傻瓜指南:如何将 LaTeX 宏添加到 \directlua?

LuaLaTeX 傻瓜指南:如何将 LaTeX 宏添加到 \directlua?

如何让下面的代码通过编译?

\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}

答案1

首先,你想将变量的值i与标记连接起来\hskip1cm,但表达式i\hskip1cm不是有效的lua表达式。你需要创建\hskip1cm一个lua字符串并将其与的值连接起来i。即:

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

但是,这也行不通,因为引号内的\是 lua 的转义字符,因此\h将被解释为转义序列,而 lua 会抱怨这\h是无效的转义序列。因此,您必须“转义转义”:

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

对于 lua 来说这没什么问题,但对于 TeX 来说却会出现问题,因为它会\\出现在 tex 定义内部,而 TeX 会尝试扩展它,从而导致麻烦。

您可以通过两种不同的方式避免此麻烦:

第一个解决方案

这是首选。将您的 lua 代码移至外部文件。例如,创建一个名为 的文件mycommand.lua,其中包含实现您的代码的 lua 函数:

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

然后,在您的tex文件中,运行 lua 文件(定义该函数并使其可用于 lua),并定义\mycommand执行该函数mycommand。这样:

\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}

请注意, 的扩展\mycommand现在不包含任何\\,因此 TeX 很满意。当 TeX 扩展 时\mycommand,这会导致mycommand()执行该函数,这将把 的连接“输出”到 tex 文档中i.."\\hskip1cm",结果为1\hskip1cm2\hskip1cm3\hskip1cmetc,这是可以的。生成的 pdf 显示预期结果:

结果

第二种解决方案

这比较丑陋,一般不推荐。您可以将任何 tex 宏放入 中\luatexluaescapestring,这将修改其扩展,以便结果为有效的 lua 字符串。因此,如果您编写例如"\luatexluaescapestring{\foo}"这将生成一个包含 扩展的复杂字符串\foo,但每个扩展都\转义为\\。将其应用于您的示例:

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

请注意,仍然需要用双引号括起来,才能得到可以连接到变量值的 lua 字符串i

答案2

对于上面的解决方案 1,为了避免反斜杠转义,我建议使用括号版本的 lua 字符串(= 字符的数量可以是任意数量,只要您使用相同的两次):

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

如果有足够声誉的人可以回复此答案,请这样做。

答案3

可以将所有小部分lua代码放在一个文件中:

\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}

相关内容