From c370529976f7e0a3ff565385b74ef7ca0a53b724 Mon Sep 17 00:00:00 2001 From: steve donovan Date: Sat, 17 Sep 2011 17:57:22 +0200 Subject: [PATCH] getting line numbers right for warnings in examples and topics; formatting function takes explicit item argument (no longer part of ldoc state) --- html/ldoc_ltp.lua | 23 +++++----- ldoc.lua | 40 +++++++++-------- ldoc/doc.lua | 5 +-- ldoc/html.lua | 2 +- ldoc/markup.lua | 108 +++++++++++++++++++++++++++------------------- ldoc/prettify.lua | 9 +++- 6 files changed, 105 insertions(+), 82 deletions(-) diff --git a/html/ldoc_ltp.lua b/html/ldoc_ltp.lua index bb472d8..a9c722d 100644 --- a/html/ldoc_ltp.lua +++ b/html/ldoc_ltp.lua @@ -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() -

$(M(module.summary))

-

$(M(module.description))

+

$(M(module.summary,module))

+

$(M(module.description,module))

# 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 $(display_name(item)) - $(M(item.summary)) + $(M(item.summary,item)) # end -- for items @@ -117,21 +116,21 @@ return [==[ # local show_parms = show_return # for kind, items in module.kinds() do

$(kind)

- $(M(module.kinds:get_section_description(kind))) + $(M(module.kinds:get_section_description(kind),nil))
-# for item in items() do ldoc.item = item -- provides context for M() +# for item in items() do
$(display_name(item))
- $(M(item.summary..' '..(item.description or ''))) + $(M(item.summary..' '..(item.description or ''),item)) # if show_parms and item.params and #item.params > 0 then

$(module.kinds:type_of(item).subnames):

    # for p in iter(item.params) do -
  • $(p): $(M(item.params[p]))
  • +
  • $(p): $(M(item.params[p],item))
  • # end -- for
# end -- if params @@ -151,7 +150,7 @@ return [==[

Returns:

    # for r in iter(item.ret) do - $(li)$(M(r))$(il) + $(li)$(M(r,item))$(il) # end -- for
# end -- if returns @@ -173,7 +172,7 @@ return [==[ # else -- if module; project-level contents # if ldoc.description then -

$(M(ldoc.description))

+

$(M(ldoc.description,nil))

# end # for kind, mods in ldoc.kinds() do @@ -183,7 +182,7 @@ return [==[ # for m in mods() do $(m.name) - $(M(m.summary)) + $(M(m.summary,m)) # end -- for modules @@ -193,7 +192,7 @@ return [==[
-generated by LDoc 0.5 +generated by LDoc 0.7
diff --git a/ldoc.lua b/ldoc.lua index cd189ae..70de1cd 100644 --- a/ldoc.lua +++ b/ldoc.lua @@ -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 diff --git a/ldoc/doc.lua b/ldoc/doc.lua index 9f9e20d..cd3a4e8 100644 --- a/ldoc/doc.lua +++ b/ldoc/doc.lua @@ -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) diff --git a/ldoc/html.lua b/ldoc/html.lua index c54c6a9..06ed1c8 100644 --- a/ldoc/html.lua +++ b/ldoc/html.lua @@ -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,{ diff --git a/ldoc/markup.lua b/ldoc/markup.lua index d6d6fd5..2b65678 100644 --- a/ldoc/markup.lua +++ b/ldoc/markup.lua @@ -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 +-- inline 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 + err = err .. ' ' .. qname + if item then item:warning(err) + else + io.stderr:write('nofile error: ',err,'\n') + end + return '???' + end + if not label then + label = ref.label + end + if not markup.plain then -- a nastiness with markdown.lua and underscores + label = label:gsub('_','\\_') + end + local res = ('%s'):format(ldoc.href(ref),label) + return res + end)) +end + +-- 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 res, append = {}, table.insert + local sections, L = {}, 1 for line in stringx.lines(txt) do local title = line:match '^##[^#]%s*(.+)' if title then - local section = F:add_document_section(title) - append(res,('\n'):format(section)) - append(res,line) - else - append(res,line) + 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,(''):format(section)) + end + append(res,line) + L = L + 1 end return concat(res,'\n') end -local function handle_reference (ldoc, 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) - else - io.stderr:write(err,'\n') - end - return '' - end - if not label then - label = ref.label - end - if not ldoc.plain then -- a nastiness with markdown.lua and underscores - label = label:gsub('_','\\_') - end - local res = ('%s'):format(ldoc.href(ref),label) - return res -end - -local ldoc_handle_reference - --- inline use same lookup as @see -local function resolve_inline_references (ldoc, txt) - return (txt:gsub('@{([^}]-)}',ldoc_handle_reference)) -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*

(.+)

%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 diff --git a/ldoc/prettify.lua b/ldoc/prettify.lua index 03fcc27..c061dd8 100644 --- a/ldoc/prettify.lua +++ b/ldoc/prettify.lua @@ -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 '
\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