这是我的 MWE:
\documentclass{article}
\newcommand{\printdata}{%
\directlua{
data = {"a", "b", "c"}
for i = 1, #data do
tex.print(data[i])
end
}
}
\begin{document}
\printdata
\end{document}
我收到以下错误消息:
! Illegal parameter number in definition of \printdata.
LuaLaTeX 似乎无法理解#
中的长度运算#data
符。我在其他地方读到过,必须在其前面加上前缀:\string#data
,但这仅在\newcommand
定义之外有效。
我该如何解决这个问题?
答案1
foo.lua
创建一个包含你的 Lua 代码的文件(例如):
function printeverything()
data = {"a", "b", "c"}
for i = 1, #data do
tex.print(data[i])
end
end
然后.tex
您可以在您的文件中使用它:
\documentclass{article}
\directlua{dofile('foo.lua')}
\newcommand{\printdata}{\directlua{printeverything()}}
\begin{document}
\printdata
\end{document}
(您不需要使用 Lua 函数 - 您只需将函数的内容转储到您的文件中并定义\newcommand{\printdata}{\directlua{dofile('foo.lua')}}
- 但如果您有多个 Lua 代码块,您可能不想为每个代码块创建单独的文件。)
解释:在使用 Lua 代码并将其放入.tex
文件中时,迟早会遇到这个问题:TeX 引擎 (LuaTeX) 会读取.tex
文件中的字符,假设某些类别代码,而字符(例如)#
在 TeX 中具有特殊含义,而 Lua 代码中则不会有这些含义。有一种解决方法(运行texdoc luacode
以查看luacode
软件包文档),但在我看来,有充分的理由避免这些解决方法。正如该文档在第一段中所说的那样:
在介绍此包中的工具之前,我首先要强调的是,管理一段非平凡的 Lua 代码的最佳方法可能是使用外部文件并从 Lua 中获取它,如所引用的文档中所述。
该
luacode
软件包提供了不同程度的命令和环境,可帮助解决其中一些问题。但是,对于除琐碎的 Lua 代码之外的所有代码,更明智的做法是使用仅包含 Lua 代码定义函数的外部文件,然后加载它并使用其函数。例如:\directlua{dofile("my-lua-functions.lua")} \newcommand*{\greatmacro}[2]{% \directlua{my_great_function("\luatexluaescapestring{#1}", #2)}}
我更喜欢将 Lua 代码放在单独的文件中的原因之一.lua
是,当 Lua 代码放在单独的文件中时,您的编辑器可能会更好地对 Lua 代码进行语法突出显示.lua
。(同样,如果 Lua 代码是单独的代码块,则在本网站上粘贴时可以获得更好的突出显示。)
答案2
您可以隐藏#
到 TeX,同时使其适用于 Lua:
\documentclass{article}
\newcommand{\printdata}{%
\directlua{
data = {"a", "b", "c"}
for i = \string##data, 1, -1 do
tex.print(data[i])
end
}%
}
\begin{document}
\printdata
\end{document}
这将打印
篮球联赛
请注意,直接调用\directlua
需要单个#
。这里的加倍是因为#
出现在定义中。
这是怎么回事?#
是 TeX 的一个特殊字符。它是定义中参数的“前缀”(可以在 中单独使用\halign
,但这不是这里的问题)。
当 TeX 吸收定义时,它不会解释宏和命令,但它会确保#
后面跟着一个数字,数字取决于所定义的宏的参数数量。如果我们想传递#
给宏的替换文本,我们需要将其加倍。参见参数中的双井号(数字符号,哈希字符)##1 是什么意思?了解详情。
这样,的替换文本\printdata
实际上将包含单个#
。但是,这#
将在宏调用时进行解释,并且它将出现在错误的上下文中;但\string#
会转换#
为可打印字符,因此在执行时不会损害宏扩展\directlua
。
因此\string##data
:加倍意味着 只\string#data
存储在 的替换文本中\printdata
。由于\directlua
首先进行 TeX 宏扩展,Lua 将只看到#data
(具有安全的#
)。