LDOC Prototype.
Produces HTML-formatted documentation from Lua comments. See http://hastebin.com/nexedayeqo.lua for example input code. This is taken from my personal stash of utility scripts and isn't guaranteed to be decent.
util.lua is the library's utility set (one function?)
parser.lua parses the comments and forms a document tree.
output.l…
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
return { | |
["html"] = { | |
value_process = function(source) | |
if (type(source) == "string") then | |
return source:gsub("\n", "\n<br />") | |
else | |
return source | |
end | |
end, | |
extension = ".html", | |
index = [=[ | |
<!doctype html> | |
<html> | |
<head> | |
<title>Index</title> | |
</head> | |
<body> | |
<ul> | |
{{!children indexnode}} | |
</ul> | |
</body> | |
</html> | |
]=], | |
indexnode = [=[ | |
<li><a href="{{path}}">{{id}} - {{title}}</a></li> | |
]=], | |
root = [=[ | |
<!doctype html> | |
<html> | |
<head> | |
<title>{{id}}</title> | |
<style type="text/css"> | |
body { | |
font-family: monospace; | |
padding: 0; | |
margin: 0; | |
background-color: black; | |
color: white; | |
} | |
.child { | |
border-top-style: groove; | |
border-bottom-style: groove; | |
border-width: 2px; | |
border-color: gray; | |
padding: 4px; | |
margin: 0; | |
} | |
.def { | |
color: #B81F11; | |
font-weight: bold; | |
} | |
.returns { | |
color: #FFE318; | |
font-weight: bold; | |
} | |
.title { | |
color: gray; | |
} | |
.desc { | |
font-style: italic; | |
} | |
.id { | |
font-style: italic; | |
} | |
.status { | |
font-weight: bold; | |
} | |
.s-needs-testing:after { | |
content: "Needs Testing"; | |
color: #FFE318; | |
} | |
.s-incomplete:after { | |
content: "Incomplete"; | |
color: #B81F11; | |
} | |
.s-production:after { | |
content: "Production"; | |
color: #089708; | |
} | |
</style> | |
</head> | |
<body> | |
<div id="root"> | |
<div id="properties"> | |
<h1 class="title">{{title}}</h1> | |
<h2>ID: <span class="id">{{id}}</span></h2> | |
<br /> | |
{{#version <h3>version $$</h3>|}} | |
{{#status <h3>Status: <span class="status s-$$"> </span></h3>|}} | |
<br /> | |
<p class="desc">{{desc}}</p> | |
<h3>TODO</h3> | |
<ul class="todos"> | |
{{#todo <li>$$</li>|no todos}} | |
</ul> | |
</div> | |
<div id="children"> | |
{{!children child}} | |
</div> | |
</div> | |
</body> | |
</html> | |
]=], | |
child = [=[ | |
<div class="child {{type}}" id="{{id}}"> | |
<h2 class="title">{{title}}</h2> | |
<p><span class="returns">{{returns}}</span> <span class="def">{{root.id}}.{{id}}{{def|()}}</span></p> | |
<p class="desc">{{desc|No description provided.}}</p> | |
</div> | |
]=] | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local arg = {...} | |
if (#arg == 0) then | |
print("Invoked improperly") | |
return | |
end | |
local lfs = require("lfs") | |
local util = require("util") | |
local parser = require("parser") | |
local output = require("output") | |
local format = require("format") | |
--assume path to be the last argument | |
local path = arg[#arg] | |
local modules = {} | |
local file_patterns = {"%.lua$", "%.ldoc$"} | |
local output_directory = path .. "/ldoc" | |
local index = parser:node("index") | |
index.children = modules | |
local unknowns = 0 | |
local total = 0 | |
local ignores = 0 | |
local faileds = 0 | |
local function parse_path(dir, modules) | |
local modules = modules or {} | |
for item in lfs.dir(dir) do | |
if (item ~= "." and item ~= "..") then | |
local path = dir .. "/" .. item | |
local mode = lfs.attributes(path, "mode") | |
if (mode == "file") then | |
local matches = false | |
for key, value in pairs(file_patterns) do | |
if (item:match(value)) then | |
matches = true | |
break | |
end | |
end | |
if (matches) then | |
local handle = io.open(path, "r") | |
if (handle) then | |
local body = handle:read("*all") | |
handle:close() | |
local parsed = parser:parse(body) | |
if (parsed) then | |
table.insert(modules, parsed) | |
else | |
ignores = ignores + 1 | |
end | |
else | |
faileds = faileds + 1 | |
print("I/O error reading " .. path) | |
end | |
end | |
elseif (mode == "directory") then | |
parse_path(path, modules) | |
end | |
end | |
end | |
return modules | |
end | |
lfs.mkdir(output_directory) | |
local parsed = parse_path(path, modules) | |
for key, mod in pairs(parsed) do | |
local id = mod.properties["id"] | |
if (not id) then | |
unknowns = unknowns + 1 | |
id = "unknown-" .. unknowns | |
end | |
local extpath = "" | |
for ext, per in id:gmatch("([^%.]+)(%.?)") do | |
extpath = extpath .. "/" .. ext | |
if (per:len() == 1) then | |
lfs.mkdir(output_directory .. extpath) | |
end | |
end | |
local total_path = output_directory .. extpath .. (format[output.style].extension or ".txt") | |
local docbody = output:process(mod) | |
local handle = io.open(total_path, "w") | |
if (handle) then | |
handle:write(docbody) | |
handle:close() | |
total = total + 1 | |
else | |
faileds = faileds + 1 | |
print("Couldn't open file for write:", total_path) | |
end | |
end | |
local ibody = output:process(index, nil, "index") | |
local ihandle = io.open(output_directory .. "/index" .. (format[output.style].extension or ".txt"), "w") | |
if (ihandle) then | |
ihandle:write(ibody) | |
ihandle:close() | |
else | |
print("Couldn't open index for write!") | |
end | |
print(([[ | |
LDOC documentation generated successfully! | |
%d files with no ID | |
%d files ignored | |
%d files failed | |
%d files succeeded]]):format(unknowns, ignores, faileds, total)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local format = require("format") | |
local util = require("util") | |
local output | |
local MODE_ARRAY = "#" | |
local MODE_RECURSE = "!" | |
local PATTERNED_SUB = "$$" | |
output = { | |
style = "html", | |
process = function(self, tree, root, doc) | |
doc = doc or "root" | |
root = root or tree | |
local style = format[self.style] | |
local output = style[doc] or ("no document '" .. doc .. "'") | |
for whole, inner in output:gmatch("({{(.-)}})") do | |
local safewhole = util.escape_string(whole) | |
local mode, middle, default = inner:match("^(%W?)([^|]+)|?(.-)$") | |
local prop, extra = middle:match("^(%S+)%s?(.-)$") | |
local rprop = prop:match("root%.(.+)") | |
local source | |
if (rprop) then | |
prop = rprop | |
source = root.properties[prop] or root[prop] | |
else | |
source = tree.properties[prop] or tree[prop] | |
end | |
if (source and style.value_process) then | |
source = style.value_process(source) or source | |
end | |
if (mode == "") then --standard replace | |
local safeprop = util.escape_string(prop) | |
output = output:gsub(safewhole, tostring(source or default)) | |
elseif (mode == MODE_ARRAY) then | |
local built = "" | |
if (source) then | |
local safesub = util.escape_string(PATTERNED_SUB) | |
if (type(source) == "table") then | |
if (#source == 0) then | |
built = default | |
else | |
for index, value in next, source do | |
built = built .. extra:gsub(safesub, tostring(value)) | |
end | |
end | |
else | |
built = built .. extra:gsub(safesub, tostring(source or default)) | |
end | |
else | |
built = default | |
end | |
output = output:gsub(safewhole, built) | |
elseif (mode == MODE_RECURSE) then | |
local built = "" | |
if (source and type(source) == "table") then | |
for index, value in next, source do | |
built = built .. self:process(value, root, extra) | |
end | |
else | |
built = default | |
end | |
output = output:gsub(safewhole, built) | |
else | |
print("unsupported mode", mode) | |
end | |
end | |
return output | |
end | |
} | |
return output |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local util = require("util") | |
local parser | |
local DOC_DISABLE = "~NODOC" | |
local TOKEN_PROPERTY = "#" | |
local TOKEN_OBJECT = "@" | |
local MODE_ARRAY = "#" | |
local ID_PROPERTY = "id" | |
parser = { | |
node = function(self, sort) | |
return { | |
type = sort, | |
path = "nil", | |
properties = {}, | |
children = {} | |
} | |
end, | |
parse = function(self, source) | |
local root = self:node("module") | |
local object = root | |
if (source:match(DOC_DISABLE)) then | |
return false | |
end | |
for line in source:gmatch("[^\r\n]+") do | |
line = line:match("%s*%-*%[*(.-)$") | |
local token = line:sub(1, 1) | |
if (token == TOKEN_PROPERTY) then | |
local safeprop = util.escape_string(TOKEN_PROPERTY) | |
local mode, key, value = line:match(safeprop .. "(.-)([%w_]*)%s(.*)") | |
if (mode == MODE_ARRAY) then | |
if (object.properties[key]) then | |
table.insert(object.properties[key], value) | |
else | |
object.properties[key] = {value} | |
end | |
else | |
if (object.properties[key]) then | |
object.properties[key] = object.properties[key] .. "\n" .. value | |
else | |
object.properties[key] = value | |
end | |
end | |
elseif (token == TOKEN_OBJECT) then | |
local sort, id = line:match(".-([%w%-_]+)%s?(.-)$") | |
if (sort) then | |
object = self:node(sort) | |
if (id:len() > 0) then | |
object.properties[ID_PROPERTY] = id | |
end | |
table.insert(root.children, object) | |
else | |
object = root | |
end | |
end | |
end | |
local id = root.properties[ID_PROPERTY] | |
if (id) then | |
root.path = id:gsub("%.", "/") .. ".html" | |
end | |
return root | |
end | |
} | |
return parser |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
local util | |
util = { | |
escape_string = function(source) | |
--This is a work in progress function | |
source = source:gsub("([%-%?%*%.%$%(%)])", "%%%0") | |
return source | |
end | |
} | |
return util |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment