getting line numbers right for warnings in examples and topics; formatting function takes explicit item argument (no longer part of ldoc state)

This commit is contained in:
steve donovan 2011-09-17 17:57:22 +02:00
parent 74531d7106
commit c370529976
6 changed files with 105 additions and 82 deletions

View File

@ -88,9 +88,8 @@ return [==[
# if ldoc.body then -- verbatim HTML as contents; 'non-code' entries # if ldoc.body then -- verbatim HTML as contents; 'non-code' entries
$(ldoc.body) $(ldoc.body)
# elseif module then -- module documentation # elseif module then -- module documentation
# ldoc.item = module -- context for M() <p>$(M(module.summary,module))</p>
<p>$(M(module.summary))</p> <p>$(M(module.description,module))</p>
<p>$(M(module.description))</p>
# if not ldoc.no_summary then # if not ldoc.no_summary then
# -- bang out the tables of item types for this module (e.g Functions, Tables, etc) # -- bang out the tables of item types for this module (e.g Functions, Tables, etc)
@ -100,7 +99,7 @@ return [==[
# for item in items() do # for item in items() do
<tr> <tr>
<td class="name" nowrap><a href="#$(item.name)">$(display_name(item))</a></td> <td class="name" nowrap><a href="#$(item.name)">$(display_name(item))</a></td>
<td class="summary">$(M(item.summary))</td> <td class="summary">$(M(item.summary,item))</td>
</tr> </tr>
# end -- for items # end -- for items
</table> </table>
@ -117,21 +116,21 @@ return [==[
# local show_parms = show_return # local show_parms = show_return
# for kind, items in module.kinds() do # for kind, items in module.kinds() do
<h2><a name="$(no_spaces(kind))"></a>$(kind)</h2> <h2><a name="$(no_spaces(kind))"></a>$(kind)</h2>
$(M(module.kinds:get_section_description(kind))) $(M(module.kinds:get_section_description(kind),nil))
<dl class="function"> <dl class="function">
# for item in items() do ldoc.item = item -- provides context for M() # for item in items() do
<dt> <dt>
<a name = "$(item.name)"></a> <a name = "$(item.name)"></a>
<strong>$(display_name(item))</strong> <strong>$(display_name(item))</strong>
</dt> </dt>
<dd> <dd>
$(M(item.summary..' '..(item.description or ''))) $(M(item.summary..' '..(item.description or ''),item))
# if show_parms and item.params and #item.params > 0 then # if show_parms and item.params and #item.params > 0 then
<h3>$(module.kinds:type_of(item).subnames):</h3> <h3>$(module.kinds:type_of(item).subnames):</h3>
<ul> <ul>
# for p in iter(item.params) do # for p in iter(item.params) do
<li><code><em>$(p)</em></code>: $(M(item.params[p]))</li> <li><code><em>$(p)</em></code>: $(M(item.params[p],item))</li>
# end -- for # end -- for
</ul> </ul>
# end -- if params # end -- if params
@ -151,7 +150,7 @@ return [==[
<h3>Returns:</h3> <h3>Returns:</h3>
<ol> <ol>
# for r in iter(item.ret) do # for r in iter(item.ret) do
$(li)$(M(r))$(il) $(li)$(M(r,item))$(il)
# end -- for # end -- for
</ol> </ol>
# end -- if returns # end -- if returns
@ -173,7 +172,7 @@ return [==[
# else -- if module; project-level contents # else -- if module; project-level contents
# if ldoc.description then # if ldoc.description then
<p>$(M(ldoc.description))</p> <p>$(M(ldoc.description,nil))</p>
# end # end
# for kind, mods in ldoc.kinds() do # for kind, mods in ldoc.kinds() do
@ -183,7 +182,7 @@ return [==[
# for m in mods() do # for m in mods() do
<tr> <tr>
<td class="name" nowrap><a href="$(no_spaces(kind))/$(m.name).html">$(m.name)</a></td> <td class="name" nowrap><a href="$(no_spaces(kind))/$(m.name).html">$(m.name)</a></td>
<td class="summary">$(M(m.summary))</td> <td class="summary">$(M(m.summary,m))</td>
</tr> </tr>
# end -- for modules # end -- for modules
</table> </table>
@ -193,7 +192,7 @@ return [==[
</div> <!-- id="content" --> </div> <!-- id="content" -->
</div> <!-- id="main" --> </div> <!-- id="main" -->
<div id="about"> <div id="about">
<i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 0.5</a></i> <i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 0.7</a></i>
</div> <!-- id="about" --> </div> <!-- id="about" -->
</div> <!-- id="container" --> </div> <!-- id="container" -->
</body> </body>

View File

@ -91,6 +91,10 @@ local file_types = {
local ldoc = {} local ldoc = {}
local add_language_extension local add_language_extension
local function override (field)
if ldoc[field] then args[field] = ldoc[field] end
end
-- aliases to existing tags can be defined. E.g. just 'p' for 'param' -- aliases to existing tags can be defined. E.g. just 'p' for 'param'
function ldoc.alias (a,tag) function ldoc.alias (a,tag)
doc.add_alias(a,tag) doc.add_alias(a,tag)
@ -252,14 +256,14 @@ end
-- where it is a list of files or directories. If specified on the command-line, we have -- where it is a list of files or directories. If specified on the command-line, we have
-- to find an optional associated config.ld, if not already loaded. -- to find an optional associated config.ld, if not already loaded.
local function process_file (f, file_list) local function process_file (f, flist)
local ext = path.extension(f) local ext = path.extension(f)
local ftype = file_types[ext] local ftype = file_types[ext]
if ftype then if ftype then
if args.verbose then print(path.basename(f)) end if args.verbose then print(path.basename(f)) end
local F,err = parse.file(f,ftype,args) local F,err = parse.file(f,ftype,args)
if err then quit(err) end if err then quit(err) end
file_list:append(F) flist:append(F)
end end
end end
@ -308,6 +312,9 @@ else
quit ("file or directory does not exist: "..quote(args.file)) quit ("file or directory does not exist: "..quote(args.file))
end end
-- create the function that renders text (descriptions and summaries)
override 'format'
ldoc.markup = markup.create(ldoc, args.format)
local multiple_files = #file_list > 1 local multiple_files = #file_list > 1
local first_module local first_module
@ -331,7 +338,7 @@ local function add_special_project_entity (f,tags,process)
F:finish() F:finish()
file_list:append(F) file_list:append(F)
item.body = text item.body = text
return item return item, F
end end
if type(ldoc.examples) == 'string' then if type(ldoc.examples) == 'string' then
@ -339,24 +346,26 @@ if type(ldoc.examples) == 'string' then
end end
if type(ldoc.examples) == 'table' then if type(ldoc.examples) == 'table' then
local prettify = require 'ldoc.prettify' local prettify = require 'ldoc.prettify'
local formatter = markup.create(ldoc,'plain')
prettify.resolve_inline_references = markup.resolve_inline_references
local function process_example (f, file_list) process_file_list (ldoc.examples, '*.lua', function(f)
local item = add_special_project_entity(f,{ local item = add_special_project_entity(f,{
class = 'example', class = 'example',
}) })
item.postprocess = prettify.lua -- wrap prettify for this example so it knows which file to blame
end -- if there's a problem
item.postprocess = function(code) return prettify.lua(f,code) end
process_file_list (ldoc.examples, '*.lua', process_example, file_list) end)
end end
if type(ldoc.readme) == 'string' then if type(ldoc.readme) == 'string' then
local item = add_special_project_entity(ldoc.readme,{ local item, F = add_special_project_entity(ldoc.readme,{
class = 'topic' class = 'topic'
}, markup.add_sections) }, markup.add_sections)
item.postprocess = markup.create(ldoc, 'markdown') -- add_sections above has created sections corresponding to the 2nd level
-- headers in the readme, which are attached to the File. So
-- we pass the File to the postprocesser can insert the section markers
-- and resolve inline @ references.
item.postprocess = function(txt) return ldoc.markup(txt,F) end
end end
---- extract modules from the file objects, resolve references and sort appropriately --- ---- extract modules from the file objects, resolve references and sort appropriately ---
@ -442,9 +451,6 @@ local function style_dir (sname)
end end
end end
local function override (field)
if ldoc[field] then args[field] = ldoc[field] end
end
-- the directories for template and stylesheet can be specified -- the directories for template and stylesheet can be specified
-- either by command-line '--template','--style' arguments or by 'template and -- either by command-line '--template','--style' arguments or by 'template and
@ -457,7 +463,6 @@ style_dir 'style'
style_dir 'template' style_dir 'template'
-- can specify format, output, dir and ext in config.ld -- can specify format, output, dir and ext in config.ld
override 'format'
override 'output' override 'output'
override 'dir' override 'dir'
override 'ext' override 'ext'
@ -490,9 +495,6 @@ if args.style == '!' or args.template == '!' then
end end
end end
-- create the function that renders text (descriptions and summaries)
ldoc.markup = markup.create(ldoc, args.format)
ldoc.single = not multiple_files and first_module or nil ldoc.single = not multiple_files and first_module or nil
ldoc.log = print ldoc.log = print

View File

@ -150,10 +150,9 @@ function File:finish()
local section_description local section_description
if this_mod.section then if this_mod.section then
item.section = this_mod.section.display_name item.section = this_mod.section.display_name
-- if it was a class, then the name should be 'Class.foo' -- if it was a class, then the name should be 'Class:foo'
if this_mod.section.type == 'type' then if this_mod.section.type == 'type' then
item.name = this_mod.section.name .. '.' .. item.name item.name = this_mod.section.name .. ':' .. item.name
item.display_name = this_mod.section.name .. ':' .. item.name
end end
section_description = this_mod.section.description section_description = this_mod.section.description
else -- otherwise, just goes into the default sections (Functions,Tables,etc) else -- otherwise, just goes into the default sections (Functions,Tables,etc)

View File

@ -126,7 +126,7 @@ function html.generate_output(ldoc, args, project)
for m in modules() do for m in modules() do
ldoc.module = m ldoc.module = m
ldoc.body = m.body ldoc.body = m.body
if ldoc.body then if ldoc.body and m.postprocess then
ldoc.body = m.postprocess(ldoc.body) ldoc.body = m.postprocess(ldoc.body)
end end
out,err = template.substitute(module_template,{ out,err = template.substitute(module_template,{

View File

@ -58,56 +58,70 @@ function markup.insert_markdown_lines (txt)
return res return res
end end
-- for readme text, the idea here is to insert module sections at ## so that -- inline <references> use same lookup as @see
-- they can appear in the contents list as a ToC local function resolve_inline_references (ldoc, txt, item)
function markup.add_sections(F, txt) return (txt:gsub('@{([^}]-)}',function (name)
local res, append = {}, table.insert
for line in stringx.lines(txt) do
local title = line:match '^##[^#]%s*(.+)'
if title then
local section = F:add_document_section(title)
append(res,('<a id="%s"></a>\n'):format(section))
append(res,line)
else
append(res,line)
end
end
return concat(res,'\n')
end
local function handle_reference (ldoc, name)
local qname,label = utils.splitv(name,'%s*|') local qname,label = utils.splitv(name,'%s*|')
if not qname then if not qname then
qname = name qname = name
end end
local ref,err = markup.process_reference(qname) local ref,err = markup.process_reference(qname)
if not ref then if not ref then
if ldoc.item then ldoc.item:warning(err) err = err .. ' ' .. qname
if item then item:warning(err)
else else
io.stderr:write(err,'\n') io.stderr:write('nofile error: ',err,'\n')
end end
return '' return '???'
end end
if not label then if not label then
label = ref.label label = ref.label
end end
if not ldoc.plain then -- a nastiness with markdown.lua and underscores if not markup.plain then -- a nastiness with markdown.lua and underscores
label = label:gsub('_','\\_') label = label:gsub('_','\\_')
end end
local res = ('<a href="%s">%s</a>'):format(ldoc.href(ref),label) local res = ('<a href="%s">%s</a>'):format(ldoc.href(ref),label)
return res return res
end))
end end
local ldoc_handle_reference -- for readme text, the idea here is to create module sections at ## so that
-- they can appear in the contents list as a ToC.
-- inline <references> use same lookup as @see function markup.add_sections(F, txt)
local function resolve_inline_references (ldoc, txt) local sections, L = {}, 1
return (txt:gsub('@{([^}]-)}',ldoc_handle_reference)) for line in stringx.lines(txt) do
local title = line:match '^##[^#]%s*(.+)'
if title then
sections[L] = F:add_document_section(title)
end end
L = L + 1
end
F.sections = sections
return txt
end
local function process_multiline_markdown(ldoc, txt, F)
local res, L, append = {}, 1, table.insert
local err_item = {
warning = function (self,msg)
io.stderr:write(F.filename..':'..L..': '..msg,'\n')
end
}
for line in stringx.lines(txt) do
line = resolve_inline_references(ldoc, line, err_item)
local section = F.sections[L]
if section then
append(res,('<a name="%s"></a>'):format(section))
end
append(res,line)
L = L + 1
end
return concat(res,'\n')
end
function markup.create (ldoc, format) function markup.create (ldoc, format)
local processor local processor
ldoc_handle_reference = utils.bind1(handle_reference,ldoc)
markup.plain = true markup.plain = true
markup.process_reference = function(name) markup.process_reference = function(name)
local mod = ldoc.single or ldoc.module local mod = ldoc.single or ldoc.module
@ -118,17 +132,21 @@ function markup.create (ldoc, format)
end end
if format == 'plain' then if format == 'plain' then
processor = function(txt) processor = function(txt, item)
if txt == nil then return '' end if txt == nil then return '' end
return resolve_inline_references(ldoc, txt) return resolve_inline_references(ldoc, txt, item)
end end
else else
local ok,formatter = pcall(require,format) local ok,formatter = pcall(require,format)
if not ok then quit("cannot load formatter: "..format) end if not ok then quit("cannot load formatter: "..format) end
markup.plain = false markup.plain = false
processor = function (txt) processor = function (txt,item)
if txt == nil then return '' end if txt == nil then return '' end
txt = resolve_inline_references(ldoc, txt) if utils.is_type(item,doc.File) then
txt = process_multiline_markdown(ldoc, txt, item)
else
txt = resolve_inline_references(ldoc, txt, item)
end
if txt:find '\n' and ldoc.extended_markdown then -- multiline text if txt:find '\n' and ldoc.extended_markdown then -- multiline text
txt = markup.insert_markdown_lines(txt) txt = markup.insert_markdown_lines(txt)
end end
@ -137,8 +155,8 @@ function markup.create (ldoc, format)
return (txt:gsub('^%s*<p>(.+)</p>%s*$','%1')) return (txt:gsub('^%s*<p>(.+)</p>%s*$','%1'))
end end
end end
markup.resolve_inline_references = function(txt) markup.resolve_inline_references = function(txt, errfn)
return resolve_inline_references(ldoc, txt) return resolve_inline_references(ldoc, txt, errfn)
end end
markup.processor = processor markup.processor = processor
prettify.resolve_inline_references = markup.resolve_inline_references prettify.resolve_inline_references = markup.resolve_inline_references

View File

@ -25,19 +25,24 @@ end
local spans = {keyword=true,number=true,string=true,comment=true} local spans = {keyword=true,number=true,string=true,comment=true}
function prettify.lua (code) function prettify.lua (fname, code)
local res = List() local res = List()
res:append(header) res:append(header)
res:append '<pre>\n' res:append '<pre>\n'
local tok = lexer.lua(code,{},{}) local tok = lexer.lua(code,{},{})
local error_reporter = {
warning = function (self,msg)
io.stderr:write(fname..':'..tok:lineno()..': '..msg,'\n')
end
}
local t,val = tok() local t,val = tok()
if not t then return nil,"empty file" end if not t then return nil,"empty file" end
while t do while t do
val = escape(val) val = escape(val)
if spans[t] then if spans[t] then
if t == 'comment' then -- may contain @{ref} if t == 'comment' then -- may contain @{ref}
val = prettify.resolve_inline_references(val) val = prettify.resolve_inline_references(val,error_reporter)
end end
res:append(span(t,val)) res:append(span(t,val))
else else