forked from enlightenment/efl
494 lines
14 KiB
Lua
494 lines
14 KiB
Lua
local util = require("util")
|
|
|
|
local dutil = require("docgen.util")
|
|
local dtree = require("docgen.doctree")
|
|
|
|
local M = {}
|
|
|
|
local root_nspace, features
|
|
|
|
M.has_feature = function(fname)
|
|
if not features then
|
|
return false
|
|
end
|
|
return not not features[fname]
|
|
end
|
|
|
|
local allowed_incflags = {
|
|
noheader = { "noheader", "showheader" },
|
|
firstseconly = { "firstseconly", "fullpage" },
|
|
readmore = { "readmore", "noreadmore" },
|
|
footer = { "footer", "nofooter" },
|
|
link = { "link", "nolink" },
|
|
permalink = { "permalink", "nopermalink" },
|
|
date = { "date", "nodate" },
|
|
mdate = { "mdate", "nomdate" },
|
|
user = { "user", "nouser" },
|
|
comments = { "comments", "nocomments" },
|
|
linkbacks = { "linkbacks", "nolinkbacks" },
|
|
tags = { "tags", "notags" },
|
|
editbutton = { "editbtn", "noeditbtn" },
|
|
redirect = { "redirect", "noredirect" },
|
|
indent = { "indent", "noindent" },
|
|
linkonly = { "linkonly", "nolinkonly" },
|
|
title = { "title", "notitle" },
|
|
pageexists = { "pageexists", "nopageexists" },
|
|
parlink = { "parlink", "noparlink" },
|
|
order = { { "id", "title", "created", "modified", "indexmenu", "custom" } },
|
|
rsort = { "rsort", "sort" },
|
|
depth = 0,
|
|
inline = true,
|
|
beforeeach = "",
|
|
aftereach = ""
|
|
}
|
|
|
|
M.Writer = util.Object:clone {
|
|
INCLUDE_PAGE = 0,
|
|
INCLUDE_SECTION = 1,
|
|
INCLUDE_NAMESPACE = 2,
|
|
INCLUDE_TAG = 3,
|
|
|
|
__ctor = function(self, path, title)
|
|
local subs
|
|
if type(path) == "table" then
|
|
subs = dutil.path_join(unpack(path))
|
|
else
|
|
subs = dutil.nspace_to_path(path)
|
|
end
|
|
dutil.mkdir_p(subs)
|
|
self.file = assert(io.open(dutil.make_page(subs), "w"))
|
|
if title then
|
|
if M.has_feature("title") then
|
|
self:write_raw("<title>", title, "</title>")
|
|
self:write_nl()
|
|
else
|
|
self:write_h(title, 1)
|
|
end
|
|
end
|
|
end,
|
|
|
|
write_raw = function(self, ...)
|
|
self.file:write(...)
|
|
return self
|
|
end,
|
|
|
|
write_nl = function(self, n)
|
|
self:write_raw(("\n"):rep(n or 1))
|
|
return self
|
|
end,
|
|
|
|
write_h = function(self, heading, level, nonl)
|
|
local s = ("="):rep(7 - level)
|
|
self:write_raw(s, " ", heading, " ", s, "\n")
|
|
if not nonl then
|
|
self:write_nl()
|
|
end
|
|
return self
|
|
end,
|
|
|
|
write_include = function(self, tp, name, flags, nonl)
|
|
local it_to_tp = {
|
|
[self.INCLUDE_PAGE] = "page",
|
|
[self.INCLUDE_SECTION] = "section",
|
|
[self.INCLUDE_NAMESPACE] = "namespace",
|
|
[self.INCLUDE_TAG] = "tagtopic"
|
|
}
|
|
if type(name) == "table" then
|
|
if name[#name] == true then
|
|
name[#name] = nil
|
|
name = ":" .. root_nspace .. ":auto:"
|
|
.. table.concat(name, ":")
|
|
elseif name[#name] == false then
|
|
name[#name] = nil
|
|
name = ":" .. root_nspace .. ":user:"
|
|
.. table.concat(name, ":")
|
|
else
|
|
name = table.concat(name, ":")
|
|
end
|
|
end
|
|
self:write_raw("{{", it_to_tp[tp], ">", name);
|
|
if flags then
|
|
if tp == self.INCLUDE_SECTION and flags.section then
|
|
self:write_raw("#", flags.section)
|
|
end
|
|
flags.section = nil
|
|
local flstr = {}
|
|
for k, v in pairs(flags) do
|
|
local allow = allowed_incflags[k]
|
|
if allow ~= nil then
|
|
if type(allow) == "boolean" then
|
|
flstr[#flstr + 1] = k
|
|
elseif type(allow) == "number" or type(allow) == "string" then
|
|
if type(v) ~= type(allow) then
|
|
error("invalid value type for flag " .. k)
|
|
end
|
|
flstr[#flstr + 1] = k .. "=" .. v
|
|
elseif type(allow) == "table" then
|
|
if type(allow[1]) == "table" then
|
|
local valid = false
|
|
for i, vv in ipairs(allow[1]) do
|
|
if v == vv then
|
|
flstr[#flstr + 1] = k .. "=" .. v
|
|
valid = true
|
|
break
|
|
end
|
|
end
|
|
if not valid then
|
|
error("invalid value " .. v .. " for flag " .. k)
|
|
end
|
|
elseif type(allow[1]) == "string" and
|
|
type(allow[2]) == "string" then
|
|
if v then
|
|
flstr[#flstr + 1] = allow[1]
|
|
else
|
|
flstr[#flstr + 1] = allow[2]
|
|
end
|
|
end
|
|
end
|
|
else
|
|
error("invalid include flag: " .. tostring(k))
|
|
end
|
|
end
|
|
flstr = table.concat(flstr, "&")
|
|
if #flstr > 0 then
|
|
self:write_raw("&", flstr)
|
|
end
|
|
end
|
|
self:write_raw("}}")
|
|
if not nonl then
|
|
self:write_nl()
|
|
end
|
|
return self
|
|
end,
|
|
|
|
write_editable = function(self, ns, name)
|
|
ns[#ns + 1] = name
|
|
ns[#ns + 1] = false
|
|
self:write_include(self.INCLUDE_PAGE, ns, {
|
|
date = false, user = false, link = false
|
|
})
|
|
-- restore the table for later reuse
|
|
-- the false gets deleted by write_include
|
|
ns[#ns] = nil
|
|
end,
|
|
|
|
write_fmt = function(self, fmt1, fmt2, ...)
|
|
self:write_raw(fmt1, ...)
|
|
self:write_raw(fmt2)
|
|
return self
|
|
end,
|
|
|
|
write_b = function(self, ...)
|
|
self:write_fmt("**", "**", ...)
|
|
return self
|
|
end,
|
|
|
|
write_i = function(self, ...)
|
|
self:write_fmt("//", "//", ...)
|
|
return self
|
|
end,
|
|
|
|
write_u = function(self, ...)
|
|
self:write_fmt("__", "__", ...)
|
|
return self
|
|
end,
|
|
|
|
write_s = function(self, ...)
|
|
self:write_fmt("<del>", "</del>", ...)
|
|
return self
|
|
end,
|
|
|
|
write_m = function(self, ...)
|
|
self:write_fmt("''", "''", ...)
|
|
return self
|
|
end,
|
|
|
|
write_sub = function(self, ...)
|
|
self:write_fmt("<sub>", "</sub>", ...)
|
|
return self
|
|
end,
|
|
|
|
write_sup = function(self, ...)
|
|
self:write_fmt("<sup>", "</sup>", ...)
|
|
return self
|
|
end,
|
|
|
|
write_br = function(self, nl)
|
|
self:write_raw("\\\\", nl and "\n" or " ")
|
|
return self
|
|
end,
|
|
|
|
write_pre_inline = function(self, ...)
|
|
self:write_fmt("%%", "%%", ...)
|
|
return self
|
|
end,
|
|
|
|
write_pre = function(self, ...)
|
|
self:write_fmt("<nowiki>\n", "\n</nowiki>", ...)
|
|
return self
|
|
end,
|
|
|
|
write_code = function(self, str, lang)
|
|
lang = lang and (" " .. lang) or ""
|
|
self:write_raw("<code" .. lang .. ">\n", str, "\n</code>\n")
|
|
end,
|
|
|
|
write_link = function(self, target, title)
|
|
if type(target) == "table" then
|
|
if target[#target] == true then
|
|
target[#target] = nil
|
|
target = ":" .. root_nspace .. ":auto:"
|
|
.. table.concat(target, ":")
|
|
elseif target[#target] == false then
|
|
target[#target] = nil
|
|
target = ":" .. root_nspace .. ":user:"
|
|
.. table.concat(target, ":")
|
|
else
|
|
target = table.concat(target, ":")
|
|
end
|
|
end
|
|
if not title then
|
|
self:write_raw("[[", target:lower(), "|", target, "]]")
|
|
return
|
|
end
|
|
target = target:lower()
|
|
if type(title) == "string" then
|
|
self:write_raw("[[", target, "|", title, "]]")
|
|
return self
|
|
end
|
|
self:write_raw("[[", target, "|")
|
|
title(self)
|
|
self:write_raw("]]")
|
|
return self
|
|
end,
|
|
|
|
write_graph = function(self, tbl)
|
|
if not M.has_feature("dot") then
|
|
return self
|
|
end
|
|
self:write_raw("<graphviz>\n")
|
|
self:write_raw("digraph ", tbl.type, " {\n")
|
|
|
|
for k, v in pairs(tbl.attrs or {}) do
|
|
self:write_raw(" ", k, " = \"", v, "\"\n")
|
|
end
|
|
|
|
local write_attrs = function(attrs)
|
|
if not attrs then
|
|
return
|
|
end
|
|
self:write_raw(" [")
|
|
local first = true
|
|
for k, v in pairs(attrs) do
|
|
if not first then
|
|
self:write_raw(", ")
|
|
end
|
|
self:write_raw(k, " = \"", v, "\"")
|
|
first = false
|
|
end
|
|
self:write_raw("]")
|
|
end
|
|
|
|
if tbl.node then
|
|
self:write_nl()
|
|
self:write_raw(" node")
|
|
write_attrs(tbl.node)
|
|
self:write_nl()
|
|
end
|
|
if tbl.edge then
|
|
if not tbl.node then self:write_nl() end
|
|
self:write_raw(" edge")
|
|
write_attrs(tbl.edge)
|
|
self:write_nl()
|
|
end
|
|
|
|
self:write_nl()
|
|
for i, v in ipairs(tbl.nodes) do
|
|
local nname = v.name
|
|
v.name = nil
|
|
self:write_raw(" ", nname)
|
|
write_attrs(v)
|
|
self:write_nl()
|
|
end
|
|
|
|
self:write_nl()
|
|
for i, v in ipairs(tbl.connections) do
|
|
local from, to, sep, attrs = v[1], v[2], (v[3] or "->")
|
|
if type(from) == "table" then
|
|
self:write_raw(" {", table.concat(from, ", "), "}")
|
|
else
|
|
self:write_raw(" ", from)
|
|
end
|
|
self:write_raw(" ", sep, " ")
|
|
if type(to) == "table" then
|
|
self:write_raw("{", table.concat(to, ", "), "}")
|
|
else
|
|
self:write_raw(to)
|
|
end
|
|
write_attrs(v[4])
|
|
self:write_nl()
|
|
end
|
|
|
|
self:write_raw("}\n</graphviz>")
|
|
end,
|
|
|
|
write_table = function(self, titles, tbl)
|
|
self:write_raw("^ ", table.concat(titles, " ^ "), " ^\n")
|
|
for i, v in ipairs(tbl) do
|
|
self:write_raw("| ", table.concat(v, " | "), " |\n")
|
|
end
|
|
return self
|
|
end,
|
|
|
|
write_list = function(self, tbl, ord)
|
|
local prec = ord and "-" or "*"
|
|
for i, v in ipairs(tbl) do
|
|
local lvl, str = 1, v
|
|
if type(v) == "table" then
|
|
lvl, str = v[1] + 1, v[2]
|
|
end
|
|
local pbeg, pend = str:match("([^\n]+)\n(.+)")
|
|
if not pbeg then
|
|
pbeg = str
|
|
end
|
|
self:write_raw((" "):rep(lvl), prec, " ", str, "\n")
|
|
if pend then
|
|
self:write_raw(pend, "\n")
|
|
end
|
|
end
|
|
return self
|
|
end,
|
|
|
|
write_par_markup = function(self, str)
|
|
self:write_raw("%%")
|
|
local f = str:gmatch(".")
|
|
local c = f()
|
|
while c do
|
|
if c == "\\" then
|
|
c = f()
|
|
if c ~= "@" and c ~= "$" then
|
|
self:write_raw("\\")
|
|
end
|
|
self:write_raw(c)
|
|
c = f()
|
|
elseif c == "$" then
|
|
c = f()
|
|
if c and c:match("[a-zA-Z_]") then
|
|
local wbuf = { c }
|
|
c = f()
|
|
while c and c:match("[a-zA-Z0-9_]") do
|
|
wbuf[#wbuf + 1] = c
|
|
c = f()
|
|
end
|
|
self:write_raw("%%''" .. table.concat(wbuf) .. "''%%")
|
|
else
|
|
self:write_raw("$")
|
|
end
|
|
elseif c == "@" then
|
|
c = f()
|
|
if c and c:match("[a-zA-Z_]") then
|
|
local rbuf = { c }
|
|
c = f()
|
|
while c and c:match("[a-zA-Z0-9_.]") do
|
|
rbuf[#rbuf + 1] = c
|
|
c = f()
|
|
end
|
|
local ldot = false
|
|
if rbuf[#rbuf] == "." then
|
|
ldot = true
|
|
rbuf[#rbuf] = nil
|
|
end
|
|
local title = table.concat(rbuf)
|
|
self:write_raw("%%")
|
|
self:write_link(dtree.ref_get(title, true), title)
|
|
self:write_raw("%%")
|
|
if ldot then
|
|
self:write_raw(".")
|
|
end
|
|
else
|
|
self:write_raw("@")
|
|
end
|
|
elseif c == "%" then
|
|
c = f()
|
|
if c == "%" then
|
|
c = f()
|
|
self:write_raw("%%<nowiki>%%</nowiki>%%")
|
|
else
|
|
self:write_raw("%")
|
|
end
|
|
else
|
|
self:write_raw(c)
|
|
c = f()
|
|
end
|
|
end
|
|
self:write_raw("%%")
|
|
return self
|
|
end,
|
|
|
|
write_par = function(self, str)
|
|
local notetypes = M.has_feature("notes") and {
|
|
["Note: "] = "<note>\n",
|
|
["Warning: "] = "<note warning>\n",
|
|
["Remark: "] = "<note tip>\n",
|
|
["TODO: "] = "<note>\n**TODO:** "
|
|
} or {}
|
|
local tag
|
|
for k, v in pairs(notetypes) do
|
|
if str:match("^" .. k) then
|
|
tag = v
|
|
str = str:sub(#k + 1)
|
|
break
|
|
end
|
|
end
|
|
if tag then
|
|
self:write_raw(tag)
|
|
self:write_par_markup(str)
|
|
self:write_raw("\n</note>")
|
|
else
|
|
self:write_par_markup(str)
|
|
end
|
|
return self
|
|
end,
|
|
|
|
write_folded = function(self, title, func)
|
|
if M.has_feature("folds") then
|
|
self:write_raw("++++ ", title, " |\n\n")
|
|
end
|
|
func(self)
|
|
if M.has_feature("folds") then
|
|
self:write_raw("\n\n++++")
|
|
end
|
|
return self
|
|
end,
|
|
|
|
finish = function(self)
|
|
self.file:close()
|
|
end
|
|
}
|
|
|
|
M.Buffer = M.Writer:clone {
|
|
__ctor = function(self)
|
|
self.buf = {}
|
|
end,
|
|
|
|
write_raw = function(self, ...)
|
|
for i, v in ipairs({ ... }) do
|
|
self.buf[#self.buf + 1] = v
|
|
end
|
|
return self
|
|
end,
|
|
|
|
finish = function(self)
|
|
self.result = table.concat(self.buf)
|
|
self.buf = {}
|
|
return self.result
|
|
end
|
|
}
|
|
|
|
M.init = function(root_ns, ftrs)
|
|
root_nspace = root_ns
|
|
features = ftrs
|
|
end
|
|
|
|
return M
|