我想将一些 ConTeXt 引用传递给 Lua 函数。就像下面的 MWE 一样,想法是通过 将表名传递给函数context.currentstructurereference
。如果我取消注释调用 context.currentstructurereference 的行,MWE 将无法编译,如果我取消注释下一行 (),则返回引用。使用括号没有帮助。
\startluacode
userdata = userdata or {}
function userdata.Test (t)
for key,value in table.sortedhash(t)
do
tex.print (value)
end
end
Paris = {
pays = "France",
région = "Ile-de-France",
megapole = "oui"
}
\stopluacode
\starttext
\startsection[title={Paris},reference={Paris}]
\startluacode
context(context.currentstructurereference)
context.par()
userdata.Test(Paris)
-- userdata.Test(context.currentstructurereference) --does not compile
-- userdata.Test(context.currentstructurereference()) --not the expected result
\stopluacode
\stopsection
\stoptext
userdata.Test(Paris)
我应该怎么做才能获得与致电相同的结果context.currentstructurereference
?
答案1
您可以使类似这样的操作起作用,但是您的代码中存在两个概念错误。
首先,该函数userdata.Test(...)
需要 Lua 表的名称作为参数。无论您做什么,context.currentstructurereference
都不会指向 Lua 表。因此,您需要做的第一件事就是更改的参数userdata.Test(...)
。更改它的最简单方法是让它需要一个字符串,这是存储相关数据的表中的键。一种选择如下:
\startluacode
userdata = userdata or {}
local references = {
["Paris"] = {
pays = "France",
région = "Ile-de-France",
megapole = "oui"
},
}
function userdata.Test (ref)
local tbl = references[ref]
for key, value in table.sortedhash(tbl)
do
tex.print (value)
end
end
\stopluacode
现在,如果我们能以某种方式将 (TeX 宏)的值context.currentstructurerefence
作为字符串传递给 Lua,那就好了。您尝试使用userdata.Test(context.currentstructurereference)
仍然不起作用。为什么?
命名空间context.
使用了一个元编程技巧:当你调用时context.something
,它大致相当于tex.print("\\something")
,但具有一些奇特的功能:
context.something("arg")
等于tex.print("\\something{arg}")
context.something({key=value}, "arg")
等于tex.print("\\something[key=value]{arg}")
该宏执行的一项奇特功能context
称为延迟处理(在 TeX 和 Lua 之间来回传递控制时需要此功能)。从高层次来看,
context.something(function ... end)
等于output of function
。
您可以通过运行以下代码来检查这一点:
\startluacode
context(function() context("Hello") end)
\stopluacode
因此,context.currentstructurereference()
是一个函数,它有效地调用了tex.sprint("\\currentstructurereference{}")
将的扩展值打印\currentstructurereference
到 TeX 流中。因此,
\startluacode
context(context.currentstructurereference)
\stopluacode
与简单调用 [^1] 大致相同context.currentstructurereference
。当然,这不适用于该userdata.Test
函数,因为:(i) 它需要一个 Lua 表(或我们上面修改后的版本中的 Lua 字符串);(ii)context.something
等于tex.print("\\something")
,因此它会写入 TeX 字符串,而 Lua 根本看不到该值。您可以做的非常简单:
\startluacode
userdata.Test("\currentstructurereference")
\stopluacode
请注意,我使用的"\currentstructurereference"
是 而不是"\\currentstructureference"
。因此,会立即展开,因此您将在遇到 时\currentstructurereference
获得 的值。这在您拥有的最小示例中有效,但如果您的实际用例更复杂,可能会失败。\currentstructurereference
\startluacode
[^1]: 严格来说,这不是真的。有一个延迟调用的概念,但我不会在这里讨论它。有关详细信息,请参阅 CLD 手册。