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
$(ldoc.body)
# elseif module then -- module documentation
# ldoc.item = module -- context for M()
<p>$(M(module.summary))</p>
<p>$(M(module.description))</p>
<p>$(M(module.summary,module))</p>
<p>$(M(module.description,module))</p>
# if not ldoc.no_summary then
# -- 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
<tr>
<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>
# end -- for items
</table>
@ -117,21 +116,21 @@ return [==[
# local show_parms = show_return
# for kind, items in module.kinds() do
<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">
# for item in items() do ldoc.item = item -- provides context for M()
# for item in items() do
<dt>
<a name = "$(item.name)"></a>
<strong>$(display_name(item))</strong>
</dt>
<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
<h3>$(module.kinds:type_of(item).subnames):</h3>
<ul>
# 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
</ul>
# end -- if params
@ -151,7 +150,7 @@ return [==[
<h3>Returns:</h3>
<ol>
# for r in iter(item.ret) do
$(li)$(M(r))$(il)
$(li)$(M(r,item))$(il)
# end -- for
</ol>
# end -- if returns
@ -173,7 +172,7 @@ return [==[
# else -- if module; project-level contents
# if ldoc.description then
<p>$(M(ldoc.description))</p>
<p>$(M(ldoc.description,nil))</p>
# end
# for kind, mods in ldoc.kinds() do
@ -183,7 +182,7 @@ return [==[
# for m in mods() do
<tr>
<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>
# end -- for modules
</table>
@ -193,7 +192,7 @@ return [==[
</div> <!-- id="content" -->
</div> <!-- id="main" -->
<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="container" -->
</body>

View File

@ -91,6 +91,10 @@ local file_types = {
local ldoc = {}
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'
function ldoc.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
-- 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 ftype = file_types[ext]
if ftype then
if args.verbose then print(path.basename(f)) end
local F,err = parse.file(f,ftype,args)
if err then quit(err) end
file_list:append(F)
flist:append(F)
end
end
@ -308,6 +312,9 @@ else
quit ("file or directory does not exist: "..quote(args.file))
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 first_module
@ -331,7 +338,7 @@ local function add_special_project_entity (f,tags,process)
F:finish()
file_list:append(F)
item.body = text
return item
return item, F
end
if type(ldoc.examples) == 'string' then
@ -339,24 +346,26 @@ if type(ldoc.examples) == 'string' then
end
if type(ldoc.examples) == 'table' then
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,{
class = 'example',
})
item.postprocess = prettify.lua
end
process_file_list (ldoc.examples, '*.lua', process_example, file_list)
-- wrap prettify for this example so it knows which file to blame
-- if there's a problem
item.postprocess = function(code) return prettify.lua(f,code) end
end)
end
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'
}, 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
---- extract modules from the file objects, resolve references and sort appropriately ---
@ -442,9 +451,6 @@ local function style_dir (sname)
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
-- either by command-line '--template','--style' arguments or by 'template and
@ -457,7 +463,6 @@ style_dir 'style'
style_dir 'template'
-- can specify format, output, dir and ext in config.ld
override 'format'
override 'output'
override 'dir'
override 'ext'
@ -490,9 +495,6 @@ if args.style == '!' or args.template == '!' then
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.log = print

View File

@ -150,10 +150,9 @@ function File:finish()
local section_description
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 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
item.display_name = this_mod.section.name .. ':' .. item.name
item.name = this_mod.section.name .. ':' .. item.name
end
section_description = this_mod.section.description
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
ldoc.module = m
ldoc.body = m.body
if ldoc.body then
if ldoc.body and m.postprocess then
ldoc.body = m.postprocess(ldoc.body)
end
out,err = template.substitute(module_template,{

View File

@ -58,56 +58,70 @@ function markup.insert_markdown_lines (txt)
return res
end
-- for readme text, the idea here is to insert module sections at ## so that
-- they can appear in the contents list as a ToC
function markup.add_sections(F, txt)
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)
-- inline <references> use same lookup as @see
local function resolve_inline_references (ldoc, txt, item)
return (txt:gsub('@{([^}]-)}',function (name)
local qname,label = utils.splitv(name,'%s*|')
if not qname then
qname = name
end
local ref,err = markup.process_reference(qname)
if not ref then
if ldoc.item then ldoc.item:warning(err)
err = err .. ' ' .. qname
if item then item:warning(err)
else
io.stderr:write(err,'\n')
io.stderr:write('nofile error: ',err,'\n')
end
return ''
return '???'
end
if not label then
label = ref.label
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('_','\\_')
end
local res = ('<a href="%s">%s</a>'):format(ldoc.href(ref),label)
return res
end))
end
local ldoc_handle_reference
-- inline <references> use same lookup as @see
local function resolve_inline_references (ldoc, txt)
return (txt:gsub('@{([^}]-)}',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.
function markup.add_sections(F, txt)
local sections, L = {}, 1
for line in stringx.lines(txt) do
local title = line:match '^##[^#]%s*(.+)'
if title then
sections[L] = F:add_document_section(title)
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)
local processor
ldoc_handle_reference = utils.bind1(handle_reference,ldoc)
markup.plain = true
markup.process_reference = function(name)
local mod = ldoc.single or ldoc.module
@ -118,27 +132,31 @@ function markup.create (ldoc, format)
end
if format == 'plain' then
processor = function(txt)
processor = function(txt, item)
if txt == nil then return '' end
return resolve_inline_references(ldoc, txt)
return resolve_inline_references(ldoc, txt, item)
end
else
local ok,formatter = pcall(require,format)
if not ok then quit("cannot load formatter: "..format) end
markup.plain = false
processor = function (txt)
processor = function (txt,item)
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
txt = markup.insert_markdown_lines(txt)
end
txt = formatter (txt)
txt = formatter(txt)
-- We will add our own paragraph tags, if needed.
return (txt:gsub('^%s*<p>(.+)</p>%s*$','%1'))
end
end
markup.resolve_inline_references = function(txt)
return resolve_inline_references(ldoc, txt)
markup.resolve_inline_references = function(txt, errfn)
return resolve_inline_references(ldoc, txt, errfn)
end
markup.processor = processor
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}
function prettify.lua (code)
function prettify.lua (fname, code)
local res = List()
res:append(header)
res:append '<pre>\n'
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()
if not t then return nil,"empty file" end
while t do
val = escape(val)
if spans[t] then
if t == 'comment' then -- may contain @{ref}
val = prettify.resolve_inline_references(val)
val = prettify.resolve_inline_references(val,error_reporter)
end
res:append(span(t,val))
else