Skip to content

Instantly share code, notes, and snippets.

@daurnimator
Created July 4, 2011 17:08
Show Gist options
  • Save daurnimator/1063631 to your computer and use it in GitHub Desktop.
Save daurnimator/1063631 to your computer and use it in GitHub Desktop.
Documentation Framework
local dt = { }
local function doc ( ... )
local args = {...}
return function ( v )
if type(v) == "function" then
local t = dt [ v ]
if t then
local tn = #t
for i,doctbl in ipairs(args) do
t[tn+1]=doctbl
end
else
dt [ v ] = args
end
return func
else
error()
end
end
end
local value = {}
value.type = "table";
value.elements = {}
value.elements.type = {
type = { "string", "table" };
desc = [[Type of the value or list of types]];
string = { "string", "table", "number", "cdata" };
table = {
list = { type="string" , desc=[[type]] };
};
}
value.elements.string = {
desc = [[]];
type = "table";
table = {
elements = {
patterns = {
type = { "string", "table" };
desc = [[Pattern or list of patterns the string must match]];
table = {
list = { type="string" , desc=[[pattern]] };
};
};
};
list = { type="string", desc=[[If present, allowed values]] };
};
}
value.elements.number = {
desc = [[
Condition or space seperated string of conditions for the number; or table of the former.
int: number is an integer (x%1 == 0)
>x: number is larger than x
<x: number is smaller than x
>=x: number is larger than or equal to x
<=x: number is smaller than or equal to x
==x: number is equal to x
eg. "int >=0" for a positive integer
]];
type = { "string" , "table" };
table = {
list = { type="string", desc=[[condition(s) for number]] };
};
}
value.elements.table = {
desc = [[]];
type = "table";
table = {
elements = {
elements = { type="table" , desc = [[Key/value in the table]] ;
table = {
elements = {
{ type="table" , table=value, desc=[[Value]] };
};
list = { type="table", table=value, desc=[[Allowed value types for elements not in element table]] };
};
};
list = { type="table", table=value, desc=[[Contents of list part of table]] };
};
};
}
value.elements.cdata = {
desc = [[cdata type or list of cdata types]];
type = { "string", "table" };
table = {
list= { type="string", desc=[[cdata type]] };
};
};
local doctbl = {
elements = {
desc = { type={ "string", "nil" }, desc=[[Description]] };
method = { desc=[[Specify the class this function is a method of; the class does not need to be specified in params.]] };
params = { type="table", desc=[[Parameters]], table={
elements = { vararg={ type="number", number={"int",">0"}, desc=[[From which element does a vararg start]] } };
list = value;
} };
returns = { type="table", desc=[[Return values]], table={list=value} };
};
}
doc{
desc = [[Adds documentation for a function, call with any number of documentation tables]] ;
params = {
vararg = 1;
{ type="table", table=doctbl, desc=[[Documentation table(s) to be added]] };
};
returns = {
{ type="function", desc=[[Call this function with the object to document.]],
["function"]={ desc = [[Call with your object to document it.]];
params = {{ [[object]] }};
returns = {{ param=1 }};
};
};
};
}(doc)
local function adddef ( out , ... )
local arg = { ... }
local n = out.n
local maxi = 0
for i , v in ipairs(arg) do
out[n+i] = "<dd>" .. v .. "</dd>"
maxi = i
end
out.n = n+maxi
end
local function newdef ( out , item , ... )
local n = out.n
out[n+1] = "<dt>" .. item .. "</dt>"
out.n = n+1
if ... then
return adddef ( out , ... )
end
end
local function newlist ( out )
out.level = out.level+1
local n = out.n
out[n+1] = "<dd><dl>"
out.n = n+1
end
local function endlist ( out )
local n = out.n
out[n+1] = "</dl></dd>"
out.n = n+1
out.level = out.level-1
end
local function concat ( out )
local v = table.concat ( out , "" , 1 , out.n )
out [ 1 ] = v
out.n = 1
return v
end
local htmlmt = {
__index = {
newdef = newdef;
adddef = adddef;
newlist = newlist;
endlist = endlist;
concat = concat;
};
__tostring = concat;
}
local function newhtml ()
return setmetatable({n=0,level=0},htmlmt)
end
--[[
<html>
<body>
</body>
</html]]
local function strpack ( o )
local typ = type(o)
if typ == "string" then
return { o }
elseif typ == "table" then
for i , v in ipairs(o) do
assert(type(v) == "string","Not a string")
end
return o
else
error("Not a string or sequence of strings",2)
end
end
local function stringval ( val )
local out = {"<ul>"}
local vt = strpack(val.type)
for i , typ in ipairs(vt) do
out [ #out + 1 ] = "<li><span class=type>" .. typ .. "</span>"
if typ == "nil" then
elseif typ == "number" then
elseif typ == "string" then
local dt = val[typ] or {}
local matches = {}
for i , value in ipairs(dt) do
matches [ #matches + 1 ] = "<span class=literal>" .. value .. "</span>"
end
for i , value in ipairs(strpack(dt.patterns or {})) do
matches [ #matches + 1 ] = "<span class=pattern>" .. value .. "</span>"
end
out [ #out + 1 ] = table.concat ( explicitvals , "|" )
elseif typ == "table" then
elseif typ == "cdata" then
elseif typ == "function" then
else
error("Invalid type")
end
out [ #out + 1 ] = "</li>"
end
out [ #out + 1 ] = "</ul>"
return table.concat(out)
end
local function html ( tbl )
local out = newhtml()
for name , v in pairs(tbl) do
local t = dt[v]
if t then
out:newdef(name)
out:newlist()
for i , doctbl in ipairs(t) do
out:newdef("Doctbl #"..i)
out:newlist()
if doctbl.desc then
out:newdef("Description",doctbl.desc)
end
out:newdef("Parameters")
for argi , argv in ipairs ( doctbl.params ) do
out:adddef( stringval(argv) )
end
if doctbl.params.vararg then
out:adddef( "..." )
end
out:newdef("Return Values")
for argi , argv in ipairs ( doctbl.returns ) do
out:adddef( stringval(argv) )
end
out:endlist()
end
out:endlist()
end
end
print(out:concat())
end
html({doc=doc})
return {
doc = doc ;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment