Several changes; if a single file is given, the module will be written directly to the output directory (no index). --output can change this name (works). Can define sections

This commit is contained in:
steve donovan 2011-06-06 18:38:02 +02:00
parent 74455c089a
commit be9c3f2f70
3 changed files with 765 additions and 688 deletions

51
doc.lua
View File

@ -17,8 +17,8 @@ local split_dotted_name = tools.split_dotted_name
local known_tags = {
param = 'M', see = 'M', usage = 'M', ['return'] = 'M', field = 'M', author='M';
class = 'id', name = 'id', pragma = 'id', alias = 'id';
copyright = 'S', summary = 'S', description = 'S', release = 'S';
module = 'T', script = 'T',['function'] = 'T', table = 'T'
copyright = 'S', summary = 'S', description = 'S', release = 'S', license = 'S';
module = 'T', script = 'T',['function'] = 'T', table = 'T', section = 'T', type = 'T';
}
known_tags._alias = {}
known_tags._project_level = {
@ -52,6 +52,11 @@ function doc.project_level(tag)
return known_tags._project_level[tag]
end
-- is it a section tag, like 'type' (class) or 'section'?
function doc.section_tag (tag)
return tag == 'section' or tag == 'type'
end
-- we process each file, resulting in a File object, which has a list of Item objects.
-- Items can be modules, scripts ('project level') or functions, tables, etc.
-- (In the code 'module' refers to any project level tag.)
@ -99,7 +104,25 @@ function File:finish()
this_mod.package = package
this_mod.mod_name = mname
this_mod.kinds = ModuleMap() -- the iterator over the module contents
else -- add the item to the module's item list
elseif doc.section_tag(item.type) then
local display_name = item.name
if display_name == 'end' then
this_mod.section = nil
else
local summary = item.summary:gsub('%.$','')
if item.type == 'type' then
display_name = 'Class '..item.name
item.module = this_mod
this_mod.items.by_name[item.name] = item
else
display_name = summary
end
item.display_name = display_name
this_mod.section = item
this_mod.kinds:add_kind(display_name,display_name)
end
else
-- add the item to the module's item list
if this_mod then
-- new-style modules will have qualified names like 'mod.foo'
local mod,fname = split_dotted_name(item.name)
@ -116,11 +139,24 @@ function File:finish()
if mod == this_mod.mod_name and this_mod.tags.pragma ~= 'nostrip' then
item.name = fname
end
-- right, this item was within a section or a 'class'
if this_mod.section then
item.section = this_mod.section.display_name
-- if it was a class, then the name should be 'Class.foo'
if this_mod.section.type == 'type' then
item.name = this_mod.section.name .. '.' .. item.name
end
else -- otherwise, just goes into the default sections (Functions,Tables,etc)
item.section = item.type
end
item.module = this_mod
local these_items = this_mod.items
these_items.by_name[item.name] = item
these_items:append(item)
-- register this item with the iterator
this_mod.kinds:add(item,these_items)
@ -191,7 +227,7 @@ function Item:finish()
self.items = List()
self.items.by_name = {}
setmetatable(self,Module)
else
elseif not doc.section_tag(self.type) then
-- params are either a function's arguments, or a table's fields, etc.
local params
if self.type == 'function' then
@ -262,7 +298,8 @@ function Module:resolve_references(modules)
return nil
end
fun_ref = mod_ref.items.by_name[name]
if fun_ref then return mod_ref,fun_ref
if fun_ref then
return mod_ref,fun_ref
else
item:warning("function not found: "..s.." in "..mod_ref.name)
end
@ -285,6 +322,10 @@ function Module:resolve_references(modules)
local mod_ref, item_ref = process_see_reference(item,see,s)
if mod_ref then
local name = item_ref and item_ref.name or ''
-- this is deeply hacky; classes have 'Class ' prepended.
if item_ref.type == 'type' then
name = 'Class_'..name
end
item.see:append {mod=mod_ref.name,name=name,label=s}
found:append{item,s}
end

View File

@ -16,7 +16,7 @@ app.require_here()
local args = lapp [[
ldoc, a documentation generator for Lua, vs 0.2 Beta
-d,--dir (default docs) output directory
-o (default 'index') output name
-o,--output (default 'index') output name
-v,--verbose verbose
-q,--quiet suppress output
-m,--module module docs as text
@ -39,17 +39,20 @@ class.ModuleMap(KindMap)
function ModuleMap:_init ()
self.klass = ModuleMap
self.fieldname = 'section'
end
ModuleMap:add_kind('function','Functions','Parameters')
ModuleMap:add_kind('table','Tables','Fields')
ModuleMap:add_kind('field','Fields')
class.ProjectMap(KindMap)
ProjectMap.project_level = true
function ProjectMap:_init ()
self.klass = ProjectMap
self.fieldname = 'type'
end
ProjectMap:add_kind('module','Modules')
@ -59,12 +62,21 @@ ProjectMap:add_kind('script','Scripts')
-- the ldoc table represents the API available in `config.ld`.
local ldoc = {}
local add_language_extension
-- aliases to existing tags can be defined. E.g. just 'p' for 'param'
function ldoc.alias (a,tag)
doc.add_alias(a,tag)
end
function ldoc.add_language_extension(ext,lang)
add_language_extension(ext,lang)
end
function ldoc.add_section (name,title,subname)
ModuleMap:add_kind(name,title,subname)
end
-- new tags can be added, which can be on a project level.
function ldoc.new_type (tag,header,project_level)
doc.add_tag(tag,doc.TAG_TYPE,project_level)
@ -316,13 +328,18 @@ local function parse_file(fname,lang)
if ldoc_comment and block then
t,v = lang:grab_block_comment(v,tok)
end
if lang:empty_comment(v) then -- ignore rest of empty start comments
t,v = tok()
end
while t and t == 'comment' do
v = lang:trim_comment(v)
append(comment,v)
t,v = tok()
if t == 'space' and not v:match '\n' then
t,v = tok()
end
end
if not t then break end -- no more file!
@ -446,6 +463,12 @@ local file_types = {
['.C'] = cc
}
function add_language_extension (ext,lang)
lang = (lang=='c' and cc) or (lang=='lua' and lua) or quit('unknown language')
if ext:sub(1,1) ~= '.' then ext = '.'..ext end
file_types[ext] = lang
end
local CONFIG_NAME = 'config.ld'
if path.isdir(args.file) then
@ -554,7 +577,7 @@ else
end
function generate_output()
-- ldoc.single = not multiple_files
ldoc.single = not multiple_files
local check_directory, check_file, writefile = tools.check_directory, tools.check_file, tools.writefile
ldoc.log = print
ldoc.kinds = project
@ -563,7 +586,10 @@ function generate_output()
ldoc.title = ldoc.title or args.title
ldoc.project = ldoc.project or args.project
local out,err = template.substitute(module_template,{ ldoc = ldoc })
local out,err = template.substitute(module_template,{
ldoc = ldoc,
module = ldoc.single and ldoc.modules[1] or nil
})
if not out then quit(err) end
check_directory(args.dir)
@ -573,9 +599,10 @@ function generate_output()
check_file(args.dir..css, path.join(args.style,css))
-- write out the module index
writefile(args.dir..'index.html',out)
writefile(args.dir..args.output..'.html',out)
-- write out the per-module documentation
if not ldoc.single then
ldoc.css = '../'..css
for kind, modules in project() do
kind = kind:lower()
@ -592,6 +619,7 @@ function generate_output()
end
end
end
end
if not args.quiet then print('output written to '..args.dir) end
end

View File

@ -44,8 +44,8 @@ end
local KindMap = class()
M.KindMap = KindMap
-- calling a KindMap returns an iterator. This returns the kind, the iterator
-- over the items of that type, and the corresponding type.
-- calling a KindMap returns an iterator. This returns the kind and the iterator
-- over the items of that type.
function KindMap:__call ()
local i = 1
local klass = self.klass
@ -58,17 +58,25 @@ function KindMap:__call ()
if not kind then return nil end
end
i = i + 1
return kind, self[kind], klass.types_by_kind[kind]
local type = klass.types_by_kind [kind].type
return kind, self[kind], type
end
end
function KindMap:type_of (item)
local klass = self.klass
local kind = klass.types_by_tag[item.type]
return klass.types_by_kind [kind]
end
-- called for each new item. It does not actually create separate lists,
-- (although that would not break the interface) but creates iterators
-- for that item type if not already created.
function KindMap:add (item,items)
local kname = self.klass.types_by_tag[item.type]
local group = item[self.fieldname]
local kname = self.klass.types_by_tag[group]
if not self[kname] then
self[kname] = M.type_iterator (items,'type',item.type)
self[kname] = M.type_iterator (items,self.fieldname,group)
end
end