[Date Prev][Date Next][Thread Prev][Thread Next]
[Date Index]
[Thread Index]
- Subject: Re: doxygen and lua modules
- From: Norman Ramsey <nr@...>
- Date: Mon, 24 Dec 2007 16:09:13 -0500
> I'm currently exploring the idea of generating documentation for the
> Lua interface of a Lua module with doxygen...
>
> In addition, I'd also like to generate some source files that will add
> in-application help strings to the module table. Something like
> module.__help = { functionx = "functionx does x", ... etc.}. I'm
> wondering also if other people have done this and if perhaps there is
> some kind of agreed upon field to put this in and format for the help
> strings.
Fidelis Assis and I have done something like this for the upcoming
new version of OSBF-Lua (which will never be released because I can't
stop tinkering with it!). We've been focusing on internal
documentation; we have commands such as
osbf internals
osbf internals util
osbf internals util.die
This thing has been a lifesaver, especially if we have to go off and
do real work for a couple of weeks and forget everything.
The implementation uses the convention that every module has an
internal value called __doc. The 'internals' module is attached to
this message. We use the same mechanism to document the C APIs
except they live in a Lua module of their own.
We have desultory ambitions in the direction of user documentation but
until things stabilize it won't happen soon.
Oh, and everything is simple ASCII. We thought html would be nice but
for us it's more important that the sources be readable and that it
work instantly on the command line. Eventually a wiki-like markup
might be a good compromise, but at the moment we're more in the
mail-handling business than in the documentation business :-)
And a distinct advantage is that there's no separate step for
extracting the doco; it's always just right there.
Norman
local modname = ...
local osbfname = string.gsub(modname, '%..-$', '')
local util = require(osbfname .. '.util')
local osbf = _G[osbfname]
local function internals(out, s)
local function show(what, t)
local l = table.sorted_keys(t)
if #l > 0 then
out:write('\n', what, ':\n')
for _, m in ipairs(l) do out:write(' ', m, '\n') end
end
end
local function undoc(modname, m, ufuns)
local doc = assert(m.__doc)
ufuns = ufuns or { }
for f in pairs(m) do
if not string.find(f, '^_') and not doc[f] then
ufuns[modname .. '.' .. f] = true
end
end
return ufuns
end
if not s then
local documented, undocumented, ufuns = { }, { }, { }
for k, v in pairs(osbf) do
if package.loaded[osbfname .. '.' .. k] == v then
(v.__doc and documented or undocumented)[k] = true
if v.__doc then
undoc(k, v, ufuns)
end
end
end
show('Documented modules', documented)
show('Undocumented modules', undocumented)
show('Undocumented functions', ufuns)
else
local module, member
if osbf[s] then
module, member = s, nil
else
module, member = string.match(s, '^([^%.]+)%.([^%.]+)$')
end
if not module then
out:write("There is no internal module called ", s, '\n')
return
end
if not osbf[module] then
out:write('There is no such internal module as ', module, '\n')
return
end
local doc = osbf[module].__doc
local function final_newline(s)
return string.match(s, '\n$') and '' or '\n'
end
local function document(k)
if string.find(k, '^__') then return end
local d = string.gsub(doc[k], '\n\n', '\n \n')
d = string.gsub(d, '\n(.)', '\n %1')
local exported = osbf[module][k] ~= nil
if not exported then
d = string.gsub(d, '^%s*function', 'local function')
end
out:write('\n', module, exported and '.' or ': ', k, ' = ', d, final_newline(d))
end
if not doc then
out:write('Internal module ', module, ' is not documented\n')
elseif not member then -- document the whole module
local first = doc.__order or { }
local sorted = table.sorted_keys(doc)
local written = { }
if doc.__overview then
out:write('=============== Overview of module ', s, ' ===============\n\n')
out:write(doc.__overview, final_newline(doc.__overview))
out:write('===================================', string.gsub(s, '.', '='),
'===============\n')
end
for _, k in ipairs(first) do
written[k] = true
document(k)
end
for _, k in ipairs(sorted) do
if not written[k] then
document(k)
end
end
show('Undocumented functions', undoc(module, osbf[module]))
else -- document just the member
if doc[member] then
document(member)
elseif osbf[module][member] then
out:write(s, " seems to exist, but it's not documented")
else
out:write('There is no such thing as ', s, '\n')
end
end
end
end
return internals