Pandoc Lua 过滤器:对不显示 table 中的所有键
Pandoc Lua Filters: pairs does not show all keys in table
从Pandoc 2.0版本开始,就有了写Lua Filters的能力。但是,在 Pandoc 2.0 中,我发现在元素 table 上使用 Lua 的 pairs
不会显示 table.
中的所有键
这里有一个最小的例子来说明这一点。在 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
完成的循环中隐藏了?
t
值隐藏在元素的metatable中:pandoc不是为每个元素分配一个t
值,而是为每个元素设置一个metatable .这样做的原因是为了在可用性和性能之间找到平衡。
将数字 table 索引返回 Haskell 比访问字符串索引值要快得多。然而,用户应该能够以直接面向对象的方式使用元素,通过可读的字符串属性访问元素组件。这就是我们为每个元素分配 metatables 的原因。 metatable 包含有关元素类型的信息(例如,Plain 与 Para 等)并定义访问器(例如,content
是 Plain 和 Para 元素中索引 0
的别名)。
因此可以通过调用 elem.t
获取元素 elem
的类型,但元素本身没有该键,metatable 有。这就是为什么在使用 pairs
遍历元素时 t
不显示的原因。可以使用 getmetatable
函数接收 metatable.
您可能会喜欢以下获取访问者名称的方法(未记录且可能会更改)。
for k, _ in pairs(getmetatable(elem).getters) do
print k
end
或者,lua 过滤器文档中关于 "Module pandoc" 的部分列出了每种元素类型的访问器。
从Pandoc 2.0版本开始,就有了写Lua Filters的能力。但是,在 Pandoc 2.0 中,我发现在元素 table 上使用 Lua 的 pairs
不会显示 table.
这里有一个最小的例子来说明这一点。在 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
完成的循环中隐藏了?
t
值隐藏在元素的metatable中:pandoc不是为每个元素分配一个t
值,而是为每个元素设置一个metatable .这样做的原因是为了在可用性和性能之间找到平衡。
将数字 table 索引返回 Haskell 比访问字符串索引值要快得多。然而,用户应该能够以直接面向对象的方式使用元素,通过可读的字符串属性访问元素组件。这就是我们为每个元素分配 metatables 的原因。 metatable 包含有关元素类型的信息(例如,Plain 与 Para 等)并定义访问器(例如,content
是 Plain 和 Para 元素中索引 0
的别名)。
因此可以通过调用 elem.t
获取元素 elem
的类型,但元素本身没有该键,metatable 有。这就是为什么在使用 pairs
遍历元素时 t
不显示的原因。可以使用 getmetatable
函数接收 metatable.
您可能会喜欢以下获取访问者名称的方法(未记录且可能会更改)。
for k, _ in pairs(getmetatable(elem).getters) do
print k
end
或者,lua 过滤器文档中关于 "Module pandoc" 的部分列出了每种元素类型的访问器。