APIDump: First attempt at outputting annotations in the HTML format

master
madmaxoft 2013-09-11 16:57:57 +02:00
parent 6dbe3296e0
commit 8012b8be6e
3 changed files with 179 additions and 85 deletions

View File

@ -0,0 +1,68 @@
-- APIDesc.lua
-- Contains the API objects' descriptions
g_APIDesc =
{
Classes =
{
cBlockArea =
{
Desc = [[
This class is used when multiple adjacent blocks are to be manipulated. Because of chunking
and multithreading, manipulating single blocks using {{api:cWorld|cWorld:SetBlock}}() is a rather
time-consuming operation (locks for exclusive access need to be obtained, chunk lookup is done
for each block), so whenever you need to manipulate multiple adjacent blocks, it's better to wrap
the operation into a cBlockArea access. cBlockArea is capable of reading / writing across chunk
boundaries, has no chunk lookups for get and set operations and is not subject to multithreading
locking (because it is not shared among threads).</p>
<p>
cBlockArea remembers its origin (MinX, MinY, MinZ coords in the Read() call) and therefore supports
absolute as well as relative get / set operations. Despite that, the contents of a cBlockArea can
be written back into the world at any coords.</p>
<p>
cBlockArea can hold any combination of the following datatypes:<ul>
<li>block types</li>
<li>block metas</li>
<li>blocklight</li>
<li>skylight</li>
</ul>
Read() and Write() functions have parameters that tell the class which datatypes to read / write.
Note that a datatype that has not been read cannot be written (FIXME).</p>
<p>
Typical usage:<ul>
<li>Create cBlockArea object</li>
<li>Read an area from the world</li>
<li>Modify blocks inside cBlockArea</li>
<li>Write the area back to a world</li>
</ul></p>
]],
Functions =
{
Clear = { Notes = "Clears the object, resets it to zero size" },
CopyFrom = { Params = "{{cBlockArea|BlockAreaSrc}}", Notes = "Copies contents from BlockAreaSrc into self"},
CopyTo = { Params = "{{cBlockArea|BlockAreaDst}}", Notes = "Copies contents from self into BlockAreaDst"},
GetBlockLight = { Params = "BlockX, BlockY, BlockZ", Return = "NIBBLETYPE", Notes = "Returns the blocklight at the specified absolute coords"},
},
},
cBlockEntity =
{
}
},
IgnoreFunctions =
{
"globals.assert",
"globals.collectgarbage",
"globals.xpcall",
}
} ;

View File

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<project> <project>
<file>
<filename>APIDesc.lua</filename>
</file>
<file> <file>
<filename>main.lua</filename> <filename>main.lua</filename>
</file> </file>

View File

@ -7,8 +7,17 @@
-- Global variables:
g_Plugin = nil;
function Initialize(Plugin) function Initialize(Plugin)
g_Plugin = Plugin;
Plugin:SetName("APIDump") Plugin:SetName("APIDump")
Plugin:SetVersion(1) Plugin:SetVersion(1)
@ -18,12 +27,9 @@ function Initialize(Plugin)
-- dump all available API functions and objects: -- dump all available API functions and objects:
-- DumpAPITxt(); -- DumpAPITxt();
-- Dump all available API objects in wiki-style tables:
-- DumpAPIWiki();
-- Dump all available API object in HTML format into a subfolder: -- Dump all available API object in HTML format into a subfolder:
DumpAPIHtml(); DumpAPIHtml();
return true return true
end end
@ -69,69 +75,30 @@ end
function DumpAPIWiki()
LOG("Dumping all available functions and constants to API_wiki.txt...");
local API, Globals = CreateAPITables();
-- Now dump the whole thing into a file, formatted as a wiki table:
local function WriteClass(a_File, a_ClassAPI)
if (#a_ClassAPI.Functions > 0) then
a_File:write("Functions:\n");
a_File:write("^ Function name ^ Parameters ^ Return value ^ Note ^\n");
for i, n in ipairs(a_ClassAPI.Functions) do
a_File:write("| " .. n[1] .. " | | | |\n");
end
a_File:write("\n\n");
end
if (#a_ClassAPI.Constants > 0) then
a_File:write("Constants:\n");
a_File:write("^ Constant ^ Value ^ Note ^\n");
for i, n in ipairs(a_ClassAPI.Constants) do
a_File:write("| " .. n[1] .. " | " .. n[2] .. " | |\n");
end
a_File:write("\n\n");
end
end
local f = io.open("API_wiki.txt", "w");
for i, n in ipairs(API) do
f:write("Class " .. n[1] .. "\n");
WriteClass(f, n[2]);
f:write("\n\n\n----------------\n");
end
f:write("globals:\n");
WriteClass(f, Globals);
f:close();
LOG("API_wiki.txt file written");
end
function CreateAPITables() function CreateAPITables()
--[[ --[[
We want an API table of the following shape: We want an API table of the following shape:
local API = { local API = {
{"cCuboid", { {
Name = "cCuboid",
Functions = { Functions = {
{"Sort"}, -- The extra table will be used to later add params, return values and notes {Name = "Sort"},
{"IsInside"} {Name = "IsInside"}
}, },
Constants = { Constants = {
} }
}}, }},
{"cBlockArea", { {
Name = "cBlockArea",
Functions = { Functions = {
"Clear", {Name = "Clear"},
"CopyFrom", {Name = "CopyFrom"},
... ...
} }
Constants = { Constants = {
{"baTypes", 0}, {Name = "baTypes", Value = 0},
{"baMetas", 1}, {Name = "baMetas", Value = 1},
... ...
} }
... ...
@ -152,9 +119,9 @@ function CreateAPITables()
local function Add(a_APIContainer, a_ClassName, a_ClassObj) local function Add(a_APIContainer, a_ClassName, a_ClassObj)
if (type(a_ClassObj) == "function") then if (type(a_ClassObj) == "function") then
table.insert(a_APIContainer.Functions, {a_ClassName}); table.insert(a_APIContainer.Functions, {Name = a_ClassName});
elseif (type(a_ClassObj) == "number") then elseif (type(a_ClassObj) == "number") then
table.insert(a_APIContainer.Constants, {a_ClassName, a_ClassObj}); table.insert(a_APIContainer.Constants, {Name = a_ClassName, Value = a_ClassObj});
end end
end end
@ -162,18 +129,18 @@ function CreateAPITables()
-- Sort the function list and constant lists: -- Sort the function list and constant lists:
table.sort(a_ClassAPI.Functions, table.sort(a_ClassAPI.Functions,
function(f1, f2) function(f1, f2)
return (f1[1] < f2[1]); return (f1.Name < f2.Name);
end end
); );
table.sort(a_ClassAPI.Constants, table.sort(a_ClassAPI.Constants,
function(c1, c2) function(c1, c2)
return (c1[1] < c2[1]); return (c1.Name < c2.Name);
end end
); );
end; end;
local function ParseClass(a_ClassObj) local function ParseClass(a_ClassName, a_ClassObj)
local res = {Functions = {}, Constants = {}}; local res = {Name = a_ClassName, Functions = {}, Constants = {}};
for i, v in pairs(a_ClassObj) do for i, v in pairs(a_ClassObj) do
Add(res, i, v); Add(res, i, v);
end end
@ -188,7 +155,7 @@ function CreateAPITables()
local StartLetter = GetChar(i, 0); local StartLetter = GetChar(i, 0);
if (StartLetter == "c") then if (StartLetter == "c") then
-- Starts with a "c", handle it as a MCS API class -- Starts with a "c", handle it as a MCS API class
table.insert(API, {i, ParseClass(v)}); table.insert(API, ParseClass(i, v));
end end
else else
Add(Globals, i, v); Add(Globals, i, v);
@ -197,7 +164,7 @@ function CreateAPITables()
SortClass(Globals); SortClass(Globals);
table.sort(API, table.sort(API,
function(c1, c2) function(c1, c2)
return (c1[1] < c2[1]); return (c1.Name < c2.Name);
end end
); );
@ -212,8 +179,13 @@ function DumpAPIHtml()
LOG("Dumping all available functions and constants to API subfolder..."); LOG("Dumping all available functions and constants to API subfolder...");
local API, Globals = CreateAPITables(); local API, Globals = CreateAPITables();
Globals.Name = "Globals";
table.insert(API, Globals);
-- Create the folder: -- Read in the descriptions:
ReadDescriptions(API);
-- Create the output folder:
os.execute("mkdir API"); os.execute("mkdir API");
-- Create a "class index" file, write each class as a link to that file, -- Create a "class index" file, write each class as a link to that file,
@ -224,9 +196,9 @@ function DumpAPIHtml()
</head><body> </head><body>
<ul> <ul>
]]); ]]);
for i, n in ipairs(API) do for i, cls in ipairs(API) do
f:write("<li><a href=\"" .. n[1] .. ".html\">" .. n[1] .. "</a></li>\n"); f:write("<li><a href=\"" .. cls.Name .. ".html\">" .. cls.Name .. "</a></li>\n");
WriteHtmlClass(n); WriteHtmlClass(cls);
end end
f:write("</ul></body></html>"); f:write("</ul></body></html>");
f:close(); f:close();
@ -235,19 +207,70 @@ end
function ReadDescriptions(a_API)
local UnexportedDocumented = {}; -- List of API objects that are documented but not exported, simply a list of names
for i, cls in ipairs(a_API) do
local APIDesc = g_APIDesc.Classes[cls.Name];
if (APIDesc ~= nil) then
cls.Desc = APIDesc.Desc;
if (APIDesc.Functions ~= nil) then
-- Assign function descriptions:
for j, func in ipairs(cls.Functions) do
-- func is {"FuncName"}, add Parameters, Return and Notes from g_APIDesc
local FnDesc = APIDesc.Functions[func.Name];
if (FnDesc ~= nil) then
func.Params = FnDesc.Params;
func.Return = FnDesc.Return;
func.Notes = FnDesc.Notes;
FnDesc.IsExported = true;
end
end -- for j, func
-- Add all non-exported function descriptions to UnexportedDocumented:
for j, func in pairs(APIDesc.Functions) do
-- TODO
end
end -- if (APIDesc.Functions ~= nil)
if (APIDesc.Constants ~= nil) then
-- Assign constant descriptions:
for j, cons in ipairs(cls.Constants) do
local CnDesc = APIDesc.Constants[cons.Name];
if (CnDesc ~= nil) then
cons.Notes = CnDesc.Notes;
CnDesc.IsExported = true;
end
end -- for j, cons
-- Add all non-exported constant descriptions to UnexportedDocumented:
for j, cons in pairs(APIDesc.Constants) do
-- TODO
end
end -- if (APIDesc.Constants ~= nil)
end
end -- for i, class
end
function WriteHtmlClass(a_ClassAPI) function WriteHtmlClass(a_ClassAPI)
local cf, err = io.open("API/" .. a_ClassAPI[1] .. ".html", "w"); local cf, err = io.open("API/" .. a_ClassAPI.Name .. ".html", "w");
if (cf == nil) then if (cf == nil) then
return; return;
end end
local function LinkifyString(a_String) local function LinkifyString(a_String)
-- TODO: Make a link out of anything with the special linkifying syntax [[link|title]] -- TODO: Make a link out of anything with the special linkifying syntax {{link|title}}
-- a_String:gsub("\[\[" .. "[ -- a_String:gsub("{{([^|]*)|[^}]*}}", "<a href=\"%1\">%2</a>");
return a_String; return a_String;
end end
cf:write([[<html><head><title>MCServer API - ]] .. a_ClassAPI[1] .. [[</title> cf:write([[<html><head><title>MCServer API - ]] .. a_ClassAPI.Name .. [[</title>
<link rel="stylesheet" type="text/css" href="main.css" /> <link rel="stylesheet" type="text/css" href="main.css" />
</head><body> </head><body>
<h1>Contents</h1> <h1>Contents</h1>
@ -255,43 +278,43 @@ function WriteHtmlClass(a_ClassAPI)
]]); ]]);
-- Write the table of contents: -- Write the table of contents:
if (#a_ClassAPI[2].Constants > 0) then if (#a_ClassAPI.Constants > 0) then
cf:write("<li><a href=\"#constants\">Constants</a></li>\n"); cf:write("<li><a href=\"#constants\">Constants</a></li>\n");
end end
if (#a_ClassAPI[2].Functions > 0) then if (#a_ClassAPI.Functions > 0) then
cf:write("<li><a href=\"#functions\">Functions</a></li>\n"); cf:write("<li><a href=\"#functions\">Functions</a></li>\n");
end end
cf:write("</ul>"); cf:write("</ul>");
-- Write the class description: -- Write the class description:
cf:write("<a name=\"desc\"><h1>" .. a_ClassAPI[1] .. "</h1></a>\n"); cf:write("<a name=\"desc\"><h1>" .. a_ClassAPI.Name .. "</h1></a>\n");
if (a_ClassAPI.Description ~= nil) then if (a_ClassAPI.Desc ~= nil) then
cf:write("<p>"); cf:write("<p>");
cf:write(n.Description); cf:write(a_ClassAPI.Desc);
cf:write("</p>\n"); cf:write("</p>\n");
end; end;
-- Write the constants: -- Write the constants:
if (#a_ClassAPI[2].Constants > 0) then if (#a_ClassAPI.Constants > 0) then
cf:write("<a name=\"constants\"><h1>Constants</h1></a>\n"); cf:write("<a name=\"constants\"><h1>Constants</h1></a>\n");
cf:write("<table><tr><th>Name</th><th>Value</th><th>Notes</th></tr>\n"); cf:write("<table><tr><th>Name</th><th>Value</th><th>Notes</th></tr>\n");
for i, n in ipairs(a_ClassAPI[2].Constants) do for i, cons in ipairs(a_ClassAPI.Constants) do
cf:write("<tr><td>" .. n[1] .. "</td>"); cf:write("<tr><td>" .. cons.Name .. "</td>");
cf:write("<td>" .. n[2] .. "</td>"); cf:write("<td>" .. cons.Value .. "</td>");
cf:write("<td>" .. LinkifyString(n.Notes or "") .. "</td></tr>\n"); cf:write("<td>" .. LinkifyString(cons.Notes or "") .. "</td></tr>\n");
end end
cf:write("</table>\n"); cf:write("</table>\n");
end end
-- Write the functions: -- Write the functions:
if (#a_ClassAPI[2].Functions > 0) then if (#a_ClassAPI.Functions > 0) then
cf:write("<a name=\"functions\"><h1>Functions</h1></a>\n"); cf:write("<a name=\"functions\"><h1>Functions</h1></a>\n");
cf:write("<table><tr><th>Name</th><th>Parameters</th><th>Return value</th><th>Notes</th></tr>\n"); cf:write("<table><tr><th>Name</th><th>Parameters</th><th>Return value</th><th>Notes</th></tr>\n");
for i, f in ipairs(a_ClassAPI[2].Functions) do for i, func in ipairs(a_ClassAPI.Functions) do
cf:write("<tr><td>" .. f[1] .. "</td>"); cf:write("<tr><td>" .. func.Name .. "</td>");
cf:write("<td>" .. LinkifyString(f.Params or "").. "</td>"); cf:write("<td>" .. LinkifyString(func.Params or "").. "</td>");
cf:write("<td>" .. LinkifyString(f.Return or "").. "</td>"); cf:write("<td>" .. LinkifyString(func.Return or "").. "</td>");
cf:write("<td>" .. LinkifyString(f.Notes or "") .. "</td></tr>\n"); cf:write("<td>" .. LinkifyString(func.Notes or "") .. "</td></tr>\n");
end end
cf:write("</table>\n"); cf:write("</table>\n");
end end