From 31693674758e83de2fedf8554c3787430f57ab8f Mon Sep 17 00:00:00 2001 From: Albert Krewinkel Date: Sat, 5 Feb 2022 12:57:19 +0100 Subject: Lua docs: allow to auto-generate Lua module documentations No documentations are generated for now, this just adds the necessary code and auto-formats file `doc/lua-filters.md`. --- tools/update-lua-module-docs.lua | 145 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 tools/update-lua-module-docs.lua (limited to 'tools/update-lua-module-docs.lua') diff --git a/tools/update-lua-module-docs.lua b/tools/update-lua-module-docs.lua new file mode 100644 index 000000000..2e32d3ea7 --- /dev/null +++ b/tools/update-lua-module-docs.lua @@ -0,0 +1,145 @@ +local ipairs, load, pairs, type = ipairs, load, pairs, type +local debug, string, table = debug, string, table +local _G = _G + +_ENV = pandoc + +local stringify = utils.stringify + +local get = function (fieldname) + return function (obj) return obj[fieldname] end +end + +local function read_blocks (txt) + return read(txt, 'commonmark').blocks +end + +local function read_inlines (txt) + return utils.blocks_to_inlines(read_blocks(txt)) +end + +local function argslist (parameters) + local required = List{} + local optional = List{} + for i, param in ipairs(parameters) do + if param.optional then + optional:insert(param.name) + else + required:extend(optional) + required:insert(param.name) + optional = List{} + end + end + if #optional == 0 then + return table.concat(required, ', ') + end + return table.concat(required, ', ') + .. '[, ' .. table.concat(optional, '[, ') .. string.rep(']', #optional) +end + +local function render_results (results) + if type(results) == 'string' then + return read_blocks(results) + elseif type(results) == 'table' then + return {BulletList( + List(results):map( + function (res) + return Para( + read_inlines(res.description) + .. {Space()} + .. Inlines('(' .. res.type .. ')') + ) + end + ) + )} + else + return Blocks{} + end +end + +local function render_function (doc, level, modulename) + local name = doc.name + level = level or 1 + local id = modulename and modulename .. '.' .. doc.name or '' + local args = argslist(doc.parameters) + local paramlist = DefinitionList( + List(doc.parameters):map( + function (p) + return { + {Code(p.name)}, + {read_blocks(p.description .. ' (' .. p.type .. ')')} + } + end + ) + ) + return Blocks{ + Header(level, name, {id}), + Plain{Code(string.format('%s (%s)', name, args))}, + } .. read_blocks(doc.description) + .. List(#doc.parameters > 0 and {Header(level+1, 'Parameters')} or {}) + .. List{paramlist} + .. List(#doc.results > 0 and {Header(level + 1, 'Returns')} or {}) + .. render_results(doc.results) +end + +local function render_field (field, level, modulename) + local id = modulename and modulename .. '.' .. field.name or '' + return {Header(level, field.name, {id})} .. read_blocks(field.description) +end + +local function render_module (doc) + local fields = Blocks{} + if #doc.fields then + fields:insert(Header(2, 'Fields', {doc.name .. '-' .. 'fields'})) + for i, fld in ipairs(doc.fields) do + fields:extend(render_field(fld, 3, doc.name)) + end + end + + local functions = Blocks{} + if #doc.functions > 0 then + functions:insert(Header(2, 'Functions', {doc.name .. '-' .. 'functions'})) + for i, fun in ipairs(doc.functions) do + functions:extend(render_function(fun, 3, doc.name)) + end + end + + return Blocks{ + Header(1, Inlines('Module ' .. doc.name), {'module-' .. doc.name}) + } .. fields .. functions +end + +--- Retrieves the documentation object for the given value. +local function documentation (value) + return debug.getregistry()['HsLua docs'][value] +end + +local function get_module_name(header) + return stringify(header):match 'Module pandoc%.([%w]*)' +end + +--- Set of modules for which documentation should be generated. +local handled_modules = {} + +return {{ + Pandoc = function (doc) + local blocks = List{} + local in_module_docs = false + for i, blk in ipairs(doc.blocks) do + if blk.t == 'Header' and blk.level == 1 then + local module_name = get_module_name(blk) + if module_name and handled_modules[module_name] then + local object = _ENV[module_name] + blocks:extend(render_module(documentation(object))) + in_module_docs = true + else + blocks:insert(blk) + in_module_docs = false + end + elseif not in_module_docs then + blocks:insert(blk) + end + end + return Pandoc(blocks, doc.meta) + end +}} -- cgit v1.2.3