git.iko.soy/typeable/pandoc
on master help sign in
Lua filters: iterate over AST element fields when using `pairs`
916db81Albert Krewinkel
data/pandoc.lua+58
@@ -73,6 +73,39 @@ local function create_accessor_functions (fn_template, accessors)
73 return res
73 return res
74end
74end
75
75
76+--- Get list of top-level fields from field descriptor table.
77+-- E.g.: `top_level_fields{'foo', {bar='baz'}, {'qux', 'quux'}}`
78+-- gives {'foo, 'bar', 'qux', 'quux'}
79+-- @local
80+local function top_level_fields (fields)
81+ local result = List:new{}
82+ for _, v in ipairs(fields) do
83+ if type(v) == 'string' then
84+ table.insert(result, v)
85+ elseif type(v) == 'table' and #v == 0 and next(v) then
86+ table.insert(result, (next(v)))
87+ else
88+ result:extend(top_level_fields(v))
89+ end
90+ end
91+ return result
92+end
93+
94+--- Creates a function which behaves like next, but respects field names.
95+-- @local
96+local function make_next_function (fields)
97+ local field_indices = {}
98+ for i, f in ipairs(fields) do
99+ field_indices[f] = i
100+ end
101+
102+ return function (t, field)
103+ local raw_idx = field == nil and 0 or field_indices[field]
104+ local next_field = fields[raw_idx + 1]
105+ return next_field, t[next_field]
106+ end
107+end
108+
76--- Create a new table which allows to access numerical indices via accessor
109--- Create a new table which allows to access numerical indices via accessor
77-- functions.
110-- functions.
78-- @local
111-- @local
@@ -102,6 +135,15 @@ local function create_accessor_behavior (tag, accessors)
102 rawset(t, k, v)
135 rawset(t, k, v)
103 end
136 end
104 end
137 end
138+ behavior.__pairs = function (t)
139+ if accessors == nil then
140+ return next, t
141+ end
142+ local iterable_fields = type(accessors) == 'string'
143+ and {accessors}
144+ or top_level_fields(accessors)
145+ return make_next_function(iterable_fields), t
146+ end
105 return behavior
147 return behavior
106end
148end
107
149
@@ -842,6 +884,14 @@ M.Attr.behavior.__newindex = function(t, k, v)
842 rawset(t, k, v)
884 rawset(t, k, v)
843 end
885 end
844end
886end
887+M.Attr.behavior.__pairs = function(t)
888+ local field_names = M.Attr.behavior._field_names
889+ local fields = {}
890+ for name, i in pairs(field_names) do
891+ fields[i] = name
892+ end
893+ return make_next_function(fields), t, nil
894+end
845
895
846-- Citation
896-- Citation
847M.Citation = AstElement:make_subtype'Citation'
897M.Citation = AstElement:make_subtype'Citation'
@@ -892,6 +942,14 @@ M.ListAttributes.behavior.__newindex = function (t, k, v)
892 rawset(t, k, v)
942 rawset(t, k, v)
893 end
943 end
894end
944end
945+M.ListAttributes.behavior.__pairs = function(t)
946+ local field_names = M.ListAttributes.behavior._field_names
947+ local fields = {}
948+ for name, i in pairs(field_names) do
949+ fields[i] = name
950+ end
951+ return make_next_function(fields), t, nil
952+end
895
953
896
954
897------------------------------------------------------------------------
955------------------------------------------------------------------------