tag parsing changed: @TAG must start on new line. Also, can handle corner case of first comment not being marked as a doc comment
This commit is contained in:
parent
7d36bf8c5e
commit
f5e2b69cff
78
ldoc.lua
78
ldoc.lua
|
@ -24,7 +24,7 @@ ldoc, a Lua documentation generator, vs 0.1 Beta
|
||||||
-p,--project (default ldoc) project name
|
-p,--project (default ldoc) project name
|
||||||
-t,--title (default Reference) page title
|
-t,--title (default Reference) page title
|
||||||
-f,--format (default plain) formatting - can be markdown
|
-f,--format (default plain) formatting - can be markdown
|
||||||
-b,--package (default '') top-level package basename (needed for module(...))
|
-b,--package (default .) top-level package basename (needed for module(...))
|
||||||
--dump debug output dump
|
--dump debug output dump
|
||||||
<file> (string) source file or directory containing source
|
<file> (string) source file or directory containing source
|
||||||
]]
|
]]
|
||||||
|
@ -97,22 +97,39 @@ end
|
||||||
|
|
||||||
local tnext = lexer.skipws
|
local tnext = lexer.skipws
|
||||||
|
|
||||||
-- This rather nasty looking code takes the collected comment block, and splits
|
-- a pattern particular to LuaDoc tag lines: the line must begin with @TAG,
|
||||||
-- it up using '@', so it is specific to the LuaDoc style of commenting.
|
-- followed by the value, which may extend over several lines.
|
||||||
|
local luadoc_tag = '%s*@(%a+)%s(.+)'
|
||||||
|
|
||||||
|
-- assumes that the doc comment consists of distinct tag lines
|
||||||
|
function parse_tags(text)
|
||||||
|
local lines = stringio.lines(text)
|
||||||
|
local preamble, line = tools.grab_while_not(lines,luadoc_tag)
|
||||||
|
local tag_items = {}
|
||||||
|
local follows
|
||||||
|
while line do
|
||||||
|
local tag,rest = line:match(luadoc_tag)
|
||||||
|
follows, line = tools.grab_while_not(lines,luadoc_tag)
|
||||||
|
append(tag_items,{tag, rest .. '\n' .. follows})
|
||||||
|
end
|
||||||
|
return preamble,tag_items
|
||||||
|
end
|
||||||
|
|
||||||
|
-- This takes the collected comment block, and uses the docstyle to
|
||||||
|
-- extract tags and values. Assume that the summary ends in a period or a question
|
||||||
|
-- mark, and everything else in the preamble is the description.
|
||||||
-- If a tag appears more than once, then its value becomes a list of strings.
|
-- If a tag appears more than once, then its value becomes a list of strings.
|
||||||
-- Alias substitution and @TYPE NAME shortcutting is handled by Item.check_tag
|
-- Alias substitution and @TYPE NAME shortcutting is handled by Item.check_tag
|
||||||
local function extract_tags (s)
|
local function extract_tags (s)
|
||||||
if s:match '^%s*$' then return {} end
|
if s:match '^%s*$' then return {} end
|
||||||
|
local preamble,tag_items = parse_tags(s)
|
||||||
local strip = tools.strip
|
local strip = tools.strip
|
||||||
local items = utils.split(s,'@')
|
local summary,description = preamble:match('^(.-)[%.?]%s(.+)')
|
||||||
local summary,description = items[1]:match('^(.-)%.%s(.+)')
|
if not summary then summary = preamble end
|
||||||
if not summary then summary = items[1] end
|
|
||||||
summary = summary .. '.'
|
summary = summary .. '.'
|
||||||
table.remove(items,1)
|
|
||||||
local tags = {summary=summary and strip(summary),description=description and strip(description)}
|
local tags = {summary=summary and strip(summary),description=description and strip(description)}
|
||||||
for _,item in ipairs(items) do
|
for _,item in ipairs(tag_items) do
|
||||||
local tag,value = item:match('(%a+)%s+(.+)%s*$')
|
local tag,value = item[1],item[2]
|
||||||
if not tag then print(s); os.exit() end
|
|
||||||
tag = Item.check_tag(tags,tag)
|
tag = Item.check_tag(tags,tag)
|
||||||
value = strip(value)
|
value = strip(value)
|
||||||
local old_value = tags[tag]
|
local old_value = tags[tag]
|
||||||
|
@ -185,8 +202,9 @@ end
|
||||||
-- that we must infer the module name.
|
-- that we must infer the module name.
|
||||||
function Lua:find_module(tok,t,v)
|
function Lua:find_module(tok,t,v)
|
||||||
while t and not (t == 'iden' and v == 'module') do
|
while t and not (t == 'iden' and v == 'module') do
|
||||||
t,v = tnext(tok)
|
|
||||||
if t == 'comment' and self:start_comment(v) then return nil,t,v end
|
if t == 'comment' and self:start_comment(v) then return nil,t,v end
|
||||||
|
--print(t,v)
|
||||||
|
t,v = tnext(tok)
|
||||||
end
|
end
|
||||||
if not t then return nil end
|
if not t then return nil end
|
||||||
t,v = tnext(tok)
|
t,v = tnext(tok)
|
||||||
|
@ -236,7 +254,7 @@ local cc = CC()
|
||||||
local function parse_file(fname,lang)
|
local function parse_file(fname,lang)
|
||||||
local line,f = 1
|
local line,f = 1
|
||||||
local F = File(fname)
|
local F = File(fname)
|
||||||
local module_found
|
local module_found, first_comment = false,true
|
||||||
|
|
||||||
local tok,f = lang.lexer(fname)
|
local tok,f = lang.lexer(fname)
|
||||||
local toks = tools.space_skip_getter(tok)
|
local toks = tools.space_skip_getter(tok)
|
||||||
|
@ -246,6 +264,8 @@ local function parse_file(fname,lang)
|
||||||
|
|
||||||
function F:warning (msg,kind)
|
function F:warning (msg,kind)
|
||||||
kind = kind or 'warning'
|
kind = kind or 'warning'
|
||||||
|
lineno() -- why is this necessary?
|
||||||
|
lineno()
|
||||||
io.stderr:write(kind..' '..fname..':'..lineno()..' '..msg,'\n')
|
io.stderr:write(kind..' '..fname..':'..lineno()..' '..msg,'\n')
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -282,20 +302,23 @@ local function parse_file(fname,lang)
|
||||||
if t == 'space' then t,v = tnext(tok) end
|
if t == 'space' then t,v = tnext(tok) end
|
||||||
|
|
||||||
local fun_follows,tags
|
local fun_follows,tags
|
||||||
|
if ldoc_comment or first_comment then
|
||||||
if ldoc_comment then
|
|
||||||
comment = table.concat(comment)
|
comment = table.concat(comment)
|
||||||
fun_follows = lang:function_follows(t,v)
|
fun_follows = lang:function_follows(t,v)
|
||||||
if fun_follows or comment:find '@' then
|
if fun_follows or comment:find '@' or first_comment then
|
||||||
tags = extract_tags(comment)
|
tags = extract_tags(comment)
|
||||||
|
-- handle the special case where the initial module comment was not
|
||||||
|
-- an ldoc style comment
|
||||||
|
if not ldoc_comment and first_comment and not tags.class then
|
||||||
|
tags.class = 'module'
|
||||||
|
ldoc_comment = true
|
||||||
|
F:warning 'Module doc comment assumed'
|
||||||
|
end
|
||||||
if doc.project_level(tags.class) then
|
if doc.project_level(tags.class) then
|
||||||
module_found = tags.name
|
module_found = tags.name
|
||||||
elseif not module_found then
|
|
||||||
module_found = tools.this_module_name(args.package,fname)
|
|
||||||
add_module({summary=''},module_found,true)
|
|
||||||
F:warning 'no module comment found'
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
first_comment = false
|
||||||
end
|
end
|
||||||
-- some hackery necessary to find the module() call
|
-- some hackery necessary to find the module() call
|
||||||
if not module_found and ldoc_comment then
|
if not module_found and ldoc_comment then
|
||||||
|
@ -370,8 +393,21 @@ if args.module then
|
||||||
args.file = fullpath
|
args.file = fullpath
|
||||||
end
|
end
|
||||||
|
|
||||||
if args.package == '' then
|
if args.file == '.' then
|
||||||
args.package = path.splitpath(args.file)
|
args.file = lfs.currentdir()
|
||||||
|
else
|
||||||
|
args.file = path.abspath(args.file)
|
||||||
|
end
|
||||||
|
|
||||||
|
local source_dir = args.file
|
||||||
|
if path.isfile(args.file) then
|
||||||
|
source_dir = path.splitpath(source_dir)
|
||||||
|
end
|
||||||
|
|
||||||
|
if args.package == '.' then
|
||||||
|
args.package = source_dir
|
||||||
|
elseif args.package == '..' then
|
||||||
|
args.package = path.splitpath(source_dir)
|
||||||
end
|
end
|
||||||
|
|
||||||
local file_types = {
|
local file_types = {
|
||||||
|
|
15
tools.lua
15
tools.lua
|
@ -125,6 +125,21 @@ function M.expand_comma_list (ls)
|
||||||
return new_ls
|
return new_ls
|
||||||
end
|
end
|
||||||
|
|
||||||
|
-- grab lines from a line iterator `iter` until the line matches the pattern.
|
||||||
|
-- Returns the joined lines and the line, which may be nil if we run out of
|
||||||
|
-- lines.
|
||||||
|
function M.grab_while_not(iter,pattern)
|
||||||
|
local line = iter()
|
||||||
|
local res = {}
|
||||||
|
while line and not line:match(pattern) do
|
||||||
|
append(res,line)
|
||||||
|
line = iter()
|
||||||
|
end
|
||||||
|
res = table.concat(res,'\n')
|
||||||
|
return res,line
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
function M.extract_identifier (value)
|
function M.extract_identifier (value)
|
||||||
return value:match('([%.:_%w]+)')
|
return value:match('([%.:_%w]+)')
|
||||||
end
|
end
|
||||||
|
|
Loading…
Reference in New Issue