自Pandoc 2.0版以来,已有能够编写Lua Filters。但是,在Pandoc 2.0中,我发现在元素表上使用Lua的pairs
并不会显示表中的所有键。
这是一个简单的例子来说明这一点。在filter.lua
我有:
function Para(elem)
io.stderr:write("A: " .. type(elem) .. "\n")
for k, v in pairs(elem) do
io.stderr:write("B: " .. k .. "\n")
end
io.stderr:write("C: " .. elem["t"] .. "\n")
io.stderr:write("D: " .. tostring(elem["c"]) .. "\n")
-- Return elem unchanged
return nil
end
现在从命令行运行:
echo "Hello." | pandoc -f markdown -t native --lua-filter filter.lua
这会产生输出:
A: table
B: c
C: Para
D: table: 0x53adb40
[Para [Str "Hello."]]
我可以将-t native
更改为-t json
,以便最后一行变为:
{"blocks":[{"t":"Para","c":[{"t":"Str","c":"Hello."}]}],"pandoc-api-version":[1,17,2],"meta":{}}
因此,从(B)的输出看,c
是elem
中唯一的关键,但从(C)可以看出,t
也是关键字我可以访问它以获取Para
。这里发生了什么,为什么用t
隐藏了循环中的pairs
键?
答案 0 :(得分:2)
t
值隐藏在元素的元表中:pandoc为每个元素设置元表,而不是为每个元素分配t
值。这样做的原因是在可用性和性能之间找到平衡。
将数字表索引返回Haskell比访问字符串索引值要快得多。但是,用户应该能够以直接面向对象的方式使用元素,通过可读的字符串属性访问元素组件。这就是我们为每个元素分配元表的原因。元表包含元素类型的信息(例如,Plain vs. Para等)并定义访问器(例如,content
是在Plain和Para元素中索引0
的别名)。
因此,可以通过调用elem
来获取元素elem.t
的类型,但元素本身没有该元素,metatable会这样做。这就是为什么t
在使用pairs
迭代元素时不显示的原因。可以使用getmetatable
函数来接收元数据。
您可能会欣赏以下方法来获取访问者的名称(未记录且可能会更改)。
for k, _ in pairs(getmetatable(elem).getters) do
print k
end
或者,关于"模块pandoc"在lua过滤器文档中列出了每种元素类型的访问器。