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
steve donovan
11 years ago
46 | 46 | script = true |
47 | 47 | } |
48 | 48 | |
49 | known_tags._module_info = { | |
50 | 'copyright','release','license','author' | |
51 | } | |
52 | ||
49 | 53 | local see_reference_handlers = {} |
50 | 54 | |
51 | 55 | |
79 | 83 | return known_tags._project_level[tag] |
80 | 84 | end |
81 | 85 | |
86 | -- is it a project level tag containing code? | |
82 | 87 | function doc.code_tag (tag) |
83 | 88 | return known_tags._code_types[tag] |
84 | 89 | end |
91 | 96 | -- is it a class tag, like 'type' or 'factory'? |
92 | 97 | function doc.class_tag (tag) |
93 | 98 | return tag == 'type' or tag == 'factory' |
99 | end | |
100 | ||
101 | function doc.module_info_tags () | |
102 | return List.iter(known_tags._module_info) | |
94 | 103 | end |
95 | 104 | |
96 | 105 | |
522 | 531 | comments:append(comment) |
523 | 532 | end |
524 | 533 | end |
534 | self.modifiers['return'] = self.modifiers['return'] or List() | |
535 | self.modifiers[field] = self.modifiers[field] or List() | |
525 | 536 | -- not all arguments may be commented: we use the formal arguments |
526 | 537 | -- if available as the authoritative list, and warn if there's an inconsistency. |
527 | 538 | if self.formal_args then |
528 | 539 | local fargs = self.formal_args |
540 | if not self.ret and fargs.return_comment then | |
541 | local retc = fargs.return_comment | |
542 | local type,rest = retc:match '([^:]+):(.*)' | |
543 | if type then | |
544 | self.modifiers['return']:append{type=type} | |
545 | retc = rest | |
546 | end | |
547 | self.ret = List{retc} | |
548 | end | |
529 | 549 | if #fargs ~= 0 then |
530 | 550 | local pnames, pcomments = names, comments |
531 | 551 | names, comments = List(),List() |
553 | 573 | comment = comment:gsub('^%-+%s*','') |
554 | 574 | local type,rest = comment:match '([^:]+):(.*)' |
555 | 575 | if type then |
556 | if not self.modifiers[field] then self.modifiers[field] = List() end | |
557 | 576 | self.modifiers[field]:append {type = type} |
558 | 577 | comment = rest |
559 | 578 | end |
621 | 640 | local rparam = self.modifiers['return'][idx] |
622 | 641 | return rparam and rparam.type or '' |
623 | 642 | end |
624 | ||
625 | 643 | |
626 | 644 | |
627 | 645 | function Item:warning(msg) |
99 | 99 | # end -- for |
100 | 100 | </ul> |
101 | 101 | # end -- if usage |
102 | # if module.info then | |
103 | <h3>Info:</h3> | |
104 | <ul> | |
105 | # for tag, value in ldoc.pairs(module.info) do | |
106 | <li><strong>$(tag)</strong>: $(value)</li> | |
107 | # end | |
108 | </ul> | |
109 | # end -- if module.info | |
110 | ||
102 | 111 | |
103 | 112 | # if not ldoc.no_summary then |
104 | 113 | # -- bang out the tables of item types for this module (e.g Functions, Tables, etc) |
19 | 19 | local template = require 'pl.template' |
20 | 20 | local tools = require 'ldoc.tools' |
21 | 21 | local markup = require 'ldoc.markup' |
22 | local doc = require 'ldoc.doc' | |
22 | 23 | local html = {} |
23 | 24 | |
24 | 25 | |
25 | 26 | local quit = utils.quit |
26 | 27 | |
27 | 28 | local function cleanup_whitespaces(text) |
28 | local lines = stringx.splitlines(text) | |
29 | for i = 1, #lines do | |
30 | lines[i] = stringx.rstrip(lines[i]) | |
31 | end | |
32 | lines[#lines + 1] = "" -- Little trick: file should end with newline | |
33 | return table.concat(lines, "\n") | |
29 | local lines = stringx.splitlines(text) | |
30 | for i = 1, #lines do | |
31 | lines[i] = stringx.rstrip(lines[i]) | |
32 | end | |
33 | lines[#lines + 1] = "" -- Little trick: file should end with newline | |
34 | return table.concat(lines, "\n") | |
35 | end | |
36 | ||
37 | local function get_module_info(m) | |
38 | local info = {} | |
39 | for tag in doc.module_info_tags() do | |
40 | local val = m.tags[tag] | |
41 | if type(val)=='table' then | |
42 | val = table.concat(val,',') | |
43 | end | |
44 | tag = stringx.title(tag) | |
45 | info[tag] = val | |
46 | end | |
47 | if next(info) then | |
48 | return info | |
49 | end | |
34 | 50 | end |
35 | 51 | |
36 | 52 | local escape_table = { ["'"] = "'", ["\""] = """, ["<"] = "<", [">"] = ">", ["&"] = "&" } |
104 | 120 | function ldoc.typename (tp) |
105 | 121 | if not tp or tp == '' then return '' end |
106 | 122 | local optional |
123 | -- ?<type> is short for ?nil|<type> | |
124 | if tp:match("^%?") and not tp:match '|' then | |
125 | tp = '?|'..tp:sub(2) | |
126 | end | |
107 | 127 | local tp2 = tp:match("%?|?(.*)") |
108 | 128 | if tp2 then |
109 | 129 | optional = true |
121 | 141 | local names = table.concat(types, ", ", 1, math.max(#types-1, 1)) |
122 | 142 | if #types > 1 then names = names.." or "..types[#types] end |
123 | 143 | if optional then |
124 | if names ~= '' then | |
125 | names = "optional "..names | |
126 | else | |
127 | names = "optional" | |
144 | if names ~= '' then | |
145 | if #types == 1 then names = "optional "..names end | |
146 | else | |
147 | names = "optional" | |
128 | 148 | end |
129 | 149 | end |
130 | 150 | return names |
138 | 158 | local css = ldoc.css |
139 | 159 | ldoc.output = args.output |
140 | 160 | ldoc.ipairs = ipairs |
161 | ldoc.pairs = pairs | |
141 | 162 | |
142 | 163 | -- in single mode there is one module and the 'index' is the |
143 | 164 | -- documentation for that module. |
146 | 167 | ldoc.kinds_allowed = {module = true, topic = true} |
147 | 168 | end |
148 | 169 | ldoc.root = true |
170 | ldoc.module.info = get_module_info(ldoc.module) | |
149 | 171 | local out,err = template.substitute(module_template,{ |
150 | 172 | ldoc = ldoc, |
151 | module = ldoc.module | |
173 | module = ldoc.module, | |
152 | 174 | }) |
153 | 175 | ldoc.root = false |
154 | 176 | if not out then quit("template failed: "..err) end |
184 | 206 | for m in modules() do |
185 | 207 | ldoc.module = m |
186 | 208 | ldoc.body = m.body |
209 | m.info = get_module_info(m) | |
187 | 210 | if ldoc.body and m.postprocess then |
188 | 211 | ldoc.body = m.postprocess(ldoc.body) |
189 | 212 | end |
47 | 47 | return preamble,tag_items |
48 | 48 | end |
49 | 49 | |
50 | local colon_tag = '%s*(%a+):%s' | |
50 | --local colon_tag = '%s*(%a+):%s' | |
51 | local colon_tag = '%s*(%S-):%s' | |
51 | 52 | local colon_tag_value = colon_tag..'(.*)' |
52 | 53 | |
53 | 54 | function parse_colon_tags (text) |
57 | 58 | while line do |
58 | 59 | local tag, rest = line:match(colon_tag_value) |
59 | 60 | follows, line = tools.grab_while_not(lines,colon_tag) |
60 | append(tag_items,{tag, rest .. '\n' .. follows}) | |
61 | local value = rest .. '\n' .. follows | |
62 | if tag:match '^[%?!]' then | |
63 | tag = tag:gsub('^!','') | |
64 | value = tag .. ' ' .. value | |
65 | tag = 'tparam' | |
66 | end | |
67 | append(tag_items,{tag, value}) | |
61 | 68 | end |
62 | 69 | return preamble,tag_items |
63 | 70 | end |
234 | 241 | else |
235 | 242 | item_follows, is_local, case = lang:item_follows(t,v,tok) |
236 | 243 | end |
237 | if item_follows or comment:find '@'then | |
244 | if item_follows or comment:find '@' or comment:find ': ' then | |
238 | 245 | tags = extract_tags(comment) |
239 | 246 | if doc.project_level(tags.class) then |
240 | 247 | module_found = tags.name |
281 | 281 | |
282 | 282 | if not ltl or not ltl[1] or #ltl[1] == 0 then return args end -- no arguments |
283 | 283 | |
284 | local function strip_comment (text) | |
285 | return text:match("%s*%-%-+%s*(.*)") | |
286 | end | |
287 | ||
284 | 288 | local function set_comment (idx,tok) |
285 | local text = stringx.rstrip(value_of(tok)) -- | |
286 | local current_comment = args.comments[args[idx]] | |
289 | local text = stringx.rstrip(value_of(tok)) | |
290 | text = strip_comment(text) | |
291 | local arg = args[idx] | |
292 | local current_comment = args.comments[arg] | |
287 | 293 | if current_comment then |
288 | text = text:match("%s*%-%-+%s*(.*)") | |
289 | args.comments[args[idx]] = current_comment .. " " .. text | |
290 | else | |
291 | args.comments[args[idx]] = text | |
292 | end | |
293 | end | |
294 | ||
295 | local function fetch_comment (tl) | |
296 | return | |
294 | text = current_comment .. " " .. text | |
295 | end | |
296 | args.comments[arg] = text | |
297 | 297 | end |
298 | 298 | |
299 | 299 | for i = 1,#ltl do |
307 | 307 | set_comment(i-1,tl[j]) |
308 | 308 | j = j + 1 |
309 | 309 | end |
310 | else -- first comment however is for the function return comment! | |
311 | args.return_comment = strip_comment(value_of(tl[i])) | |
312 | j = j + 1 | |
310 | 313 | end |
311 | 314 | if #tl > 1 then |
312 | 315 | args:append(value_of(tl[j])) |
0 | ------------ | |
1 | -- Yet another module. | |
2 | -- @module four | |
3 | -- Description can continue after simple tags, if you | |
4 | -- like | |
5 | -- @author bob, james | |
6 | -- @license MIT | |
7 | -- @copyright InfoReich 2013 | |
8 | ||
9 | --- a function with typed args. | |
10 | -- Note the the standard tparam aliases | |
11 | -- @string name person's name | |
12 | -- @int age | |
13 | -- @treturn string | |
14 | function one (name,age) | |
15 | end | |
16 | ||
17 | --- second useless function. | |
18 | -- If you hate @ tags, you can use colons. | |
19 | -- Optional type specifiers are allowed in this format. | |
20 | -- As an extension, '?' is short for '?|'. | |
21 | -- Note how these types are rendered! | |
22 | -- string: name | |
23 | -- int: age | |
24 | -- ?person2: options | |
25 | -- treturn: ?table|string | |
26 | function two (name,age,options) | |
27 | end | |
28 | ||
29 | --- third useless function. | |
30 | -- Can always put comments inline, may | |
31 | -- be multiple. | |
32 | -- note that first comment is refers to return | |
33 | function three ( -- person: | |
34 | name, -- string: person's name | |
35 | age -- int: | |
36 | -- not less than zero! | |
37 | ) | |
38 | ||
39 | --- an implicit table. | |
40 | -- Again, we can use the comments | |
41 | person = { | |
42 | name = '', -- string: name of person | |
43 | age = 0, -- int: | |
44 | } | |
45 | ||
46 | --- an explicit table. | |
47 | -- Can now use tparam aliases in table defns | |
48 | -- @string name | |
49 | -- @int age | |
50 | -- @table person2 | |
51 | ||
52 | --- explicit table in colon format. | |
53 | -- Note how '!' lets you use a type name directly. | |
54 | -- string: surname | |
55 | -- string: birthdate | |
56 | -- !person2: options | |
57 | -- table: person3 |