From 1bb83924bbe277f7d31c370e3ba1f84a880bb7bf Mon Sep 17 00:00:00 2001 From: steve donovan Date: Mon, 31 Dec 2012 14:52:00 +0200 Subject: [PATCH] in implicit function style (a la Geoff) the first comment refers to the return value. In colon style, an exclamation mark allows a typename to be directly used as a 'tag'. The word 'optional' is only issued if we have either nil or a type --- ldoc/doc.lua | 22 ++++++++++++++-- ldoc/html.lua | 45 ++++++++++++++++++++++++-------- ldoc/html/ldoc_ltp.lua | 9 +++++++ ldoc/parse.lua | 13 +++++++--- ldoc/tools.lua | 25 ++++++++++-------- tests/styles/dof.lua | 1 - tests/styles/four.lua | 58 ++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 145 insertions(+), 28 deletions(-) delete mode 100644 tests/styles/dof.lua create mode 100644 tests/styles/four.lua diff --git a/ldoc/doc.lua b/ldoc/doc.lua index 0119426..989e018 100644 --- a/ldoc/doc.lua +++ b/ldoc/doc.lua @@ -47,6 +47,10 @@ known_tags._code_types = { script = true } +known_tags._module_info = { + 'copyright','release','license','author' +} + local see_reference_handlers = {} @@ -80,6 +84,7 @@ function doc.project_level(tag) return known_tags._project_level[tag] end +-- is it a project level tag containing code? function doc.code_tag (tag) return known_tags._code_types[tag] end @@ -94,6 +99,10 @@ function doc.class_tag (tag) return tag == 'type' or tag == 'factory' end +function doc.module_info_tags () + return List.iter(known_tags._module_info) +end + -- annotation tags can appear anywhere in the code and may contain of these tags: known_tags._annotation_tags = { @@ -523,10 +532,21 @@ function Item:finish() comments:append(comment) end end + self.modifiers['return'] = self.modifiers['return'] or List() + self.modifiers[field] = self.modifiers[field] or List() -- not all arguments may be commented: we use the formal arguments -- if available as the authoritative list, and warn if there's an inconsistency. if self.formal_args then local fargs = self.formal_args + if not self.ret and fargs.return_comment then + local retc = fargs.return_comment + local type,rest = retc:match '([^:]+):(.*)' + if type then + self.modifiers['return']:append{type=type} + retc = rest + end + self.ret = List{retc} + end if #fargs ~= 0 then local pnames, pcomments = names, comments names, comments = List(),List() @@ -554,7 +574,6 @@ function Item:finish() comment = comment:gsub('^%-+%s*','') local type,rest = comment:match '([^:]+):(.*)' if type then - if not self.modifiers[field] then self.modifiers[field] = List() end self.modifiers[field]:append {type = type} comment = rest end @@ -624,7 +643,6 @@ function Item:type_of_ret(idx) end - function Item:warning(msg) local file = self.file and self.file.filename if type(file) == 'table' then pretty.dump(file); file = '?' end diff --git a/ldoc/html.lua b/ldoc/html.lua index d78a170..8f7a5e5 100644 --- a/ldoc/html.lua +++ b/ldoc/html.lua @@ -20,18 +20,34 @@ local stringx = require 'pl.stringx' local template = require 'pl.template' local tools = require 'ldoc.tools' local markup = require 'ldoc.markup' +local doc = require 'ldoc.doc' local html = {} local quit = utils.quit local function cleanup_whitespaces(text) - local lines = stringx.splitlines(text) - for i = 1, #lines do - lines[i] = stringx.rstrip(lines[i]) - end - lines[#lines + 1] = "" -- Little trick: file should end with newline - return table.concat(lines, "\n") + local lines = stringx.splitlines(text) + for i = 1, #lines do + lines[i] = stringx.rstrip(lines[i]) + end + lines[#lines + 1] = "" -- Little trick: file should end with newline + return table.concat(lines, "\n") +end + +local function get_module_info(m) + local info = {} + for tag in doc.module_info_tags() do + local val = m.tags[tag] + if type(val)=='table' then + val = table.concat(val,',') + end + tag = stringx.title(tag) + info[tag] = val + end + if next(info) then + return info + end end local escape_table = { ["'"] = "'", ["\""] = """, ["<"] = "<", [">"] = ">", ["&"] = "&" } @@ -105,6 +121,10 @@ function html.generate_output(ldoc, args, project) function ldoc.typename (tp) if not tp or tp == '' then return '' end local optional + -- ? is short for ?nil| + if tp:match("^%?") and not tp:match '|' then + tp = '?|'..tp:sub(2) + end local tp2 = tp:match("%?|?(.*)") if tp2 then optional = true @@ -122,10 +142,10 @@ function html.generate_output(ldoc, args, project) local names = table.concat(types, ", ", 1, math.max(#types-1, 1)) if #types > 1 then names = names.." or "..types[#types] end if optional then - if names ~= '' then - names = "optional "..names - else - names = "optional" + if names ~= '' then + if #types == 1 then names = "optional "..names end + else + names = "optional" end end return names @@ -139,6 +159,7 @@ function html.generate_output(ldoc, args, project) local css = ldoc.css ldoc.output = args.output ldoc.ipairs = ipairs + ldoc.pairs = pairs -- in single mode there is one module and the 'index' is the -- documentation for that module. @@ -147,9 +168,10 @@ function html.generate_output(ldoc, args, project) ldoc.kinds_allowed = {module = true, topic = true} end ldoc.root = true + ldoc.module.info = get_module_info(ldoc.module) local out,err = template.substitute(module_template,{ ldoc = ldoc, - module = ldoc.module + module = ldoc.module, }) ldoc.root = false if not out then quit("template failed: "..err) end @@ -185,6 +207,7 @@ function html.generate_output(ldoc, args, project) for m in modules() do ldoc.module = m ldoc.body = m.body + m.info = get_module_info(m) if ldoc.body and m.postprocess then ldoc.body = m.postprocess(ldoc.body) end diff --git a/ldoc/html/ldoc_ltp.lua b/ldoc/html/ldoc_ltp.lua index ea5e19f..e59de43 100644 --- a/ldoc/html/ldoc_ltp.lua +++ b/ldoc/html/ldoc_ltp.lua @@ -100,6 +100,15 @@ return [==[ # end -- for # end -- if usage +# if module.info then +

Info:

+
    +# for tag, value in ldoc.pairs(module.info) do +
  • $(tag): $(value)
  • +# end +
+# end -- if module.info + # if not ldoc.no_summary then # -- bang out the tables of item types for this module (e.g Functions, Tables, etc) diff --git a/ldoc/parse.lua b/ldoc/parse.lua index 4e97294..7d0838c 100644 --- a/ldoc/parse.lua +++ b/ldoc/parse.lua @@ -48,7 +48,8 @@ function parse_at_tags(text) return preamble,tag_items end -local colon_tag = '%s*(%a+):%s' +--local colon_tag = '%s*(%a+):%s' +local colon_tag = '%s*(%S-):%s' local colon_tag_value = colon_tag..'(.*)' function parse_colon_tags (text) @@ -58,7 +59,13 @@ function parse_colon_tags (text) while line do local tag, rest = line:match(colon_tag_value) follows, line = tools.grab_while_not(lines,colon_tag) - append(tag_items,{tag, rest .. '\n' .. follows}) + local value = rest .. '\n' .. follows + if tag:match '^[%?!]' then + tag = tag:gsub('^!','') + value = tag .. ' ' .. value + tag = 'tparam' + end + append(tag_items,{tag, value}) end return preamble,tag_items end @@ -235,7 +242,7 @@ local function parse_file(fname, lang, package, args) else item_follows, is_local, case = lang:item_follows(t,v,tok) end - if item_follows or comment:find '@'then + if item_follows or comment:find '@' or comment:find ': ' then tags = extract_tags(comment) if doc.project_level(tags.class) then module_found = tags.name diff --git a/ldoc/tools.lua b/ldoc/tools.lua index d9266e3..e2b2c8b 100644 --- a/ldoc/tools.lua +++ b/ldoc/tools.lua @@ -282,19 +282,19 @@ function M.get_parameters (tok,endtoken,delim) if not ltl or not ltl[1] or #ltl[1] == 0 then return args end -- no arguments - local function set_comment (idx,tok) - local text = stringx.rstrip(value_of(tok)) -- - local current_comment = args.comments[args[idx]] - if current_comment then - text = text:match("%s*%-%-+%s*(.*)") - args.comments[args[idx]] = current_comment .. " " .. text - else - args.comments[args[idx]] = text - end + local function strip_comment (text) + return text:match("%s*%-%-+%s*(.*)") end - local function fetch_comment (tl) - return + local function set_comment (idx,tok) + local text = stringx.rstrip(value_of(tok)) + text = strip_comment(text) + local arg = args[idx] + local current_comment = args.comments[arg] + if current_comment then + text = current_comment .. " " .. text + end + args.comments[arg] = text end for i = 1,#ltl do @@ -308,6 +308,9 @@ function M.get_parameters (tok,endtoken,delim) set_comment(i-1,tl[j]) j = j + 1 end + else -- first comment however is for the function return comment! + args.return_comment = strip_comment(value_of(tl[i])) + j = j + 1 end if #tl > 1 then args:append(value_of(tl[j])) diff --git a/tests/styles/dof.lua b/tests/styles/dof.lua deleted file mode 100644 index a596c57..0000000 --- a/tests/styles/dof.lua +++ /dev/null @@ -1 +0,0 @@ -print(arg,DOOFUS) diff --git a/tests/styles/four.lua b/tests/styles/four.lua new file mode 100644 index 0000000..f89e42f --- /dev/null +++ b/tests/styles/four.lua @@ -0,0 +1,58 @@ +------------ +-- Yet another module. +-- @module four +-- Description can continue after simple tags, if you +-- like +-- @author bob, james +-- @license MIT +-- @copyright InfoReich 2013 + +--- a function with typed args. +-- Note the the standard tparam aliases +-- @string name person's name +-- @int age +-- @treturn string +function one (name,age) +end + +--- second useless function. +-- If you hate @ tags, you can use colons. +-- Optional type specifiers are allowed in this format. +-- As an extension, '?' is short for '?|'. +-- Note how these types are rendered! +-- string: name +-- int: age +-- ?person2: options +-- treturn: ?table|string +function two (name,age,options) +end + +--- third useless function. +-- Can always put comments inline, may +-- be multiple. +-- note that first comment is refers to return +function three ( -- person: + name, -- string: person's name + age -- int: + -- not less than zero! +) + +--- an implicit table. +-- Again, we can use the comments +person = { + name = '', -- string: name of person + age = 0, -- int: +} + +--- an explicit table. +-- Can now use tparam aliases in table defns +-- @string name +-- @int age +-- @table person2 + +--- explicit table in colon format. +-- Note how '!' lets you use a type name directly. +-- string: surname +-- string: birthdate +-- !person2: options +-- table: person3