Merge tag 'upstream/1.4.3'
new 1.5 RC
Julian Wollrath
9 years ago
0 | ## Version 1.4.2 | |
1 | ||
2 | ### Features | |
3 | ||
4 | * Can define fields/properties of objects; `readonly` modifier supported (#93) | |
5 | * Can switch off auto-linking to Lua manual with `no_lua_ref` | |
6 | * Module sorting is off by default, use `sort_modules=true` | |
7 | * References to 'classes' now work properly | |
8 | * Option to use first Markdown title instead of file names with `use_markdown_titles` | |
9 | * Automatic `Metamethods` and `Methods` sections generated for `classmod` classes | |
10 | * `unqualified=true` to strip package names on sidebar (#110) | |
11 | * Custom tags (which may be hidden) | |
12 | * Custom Display Name handlers | |
13 | ||
14 | ### Fixes | |
15 | ||
16 | * stricter about doc comments, now excludes common '----- XXXXX ----' pattern | |
17 | * no longer expects space after `##` in Markdown (#96) | |
18 | * Section lookup was broken | |
19 | * With `export` tag, decide whether method is static or not | |
20 | * `classmod` classes now respect custom sections (#113) | |
21 | * Minor issues with prettification | |
22 | * Command-line flags set explicitly take precendence over configuration file values. | |
23 | * Boilerplate Lua block comment ignored properly (#137) | |
24 | * Inline links with underscores sorted (#22) | |
25 | * Info section ordering is now consistent (#150) | |
26 | ||
27 | ## Version 1.4.0 | |
28 | ||
29 | ### Features | |
30 | ||
31 | * `sort=true` to sort items within sections alphabetically | |
32 | * `@set` tag in module comments; e.g, can say `@set sort=true` | |
33 | * `@classmod` tag for defining modules that export one class | |
34 | * can generate Markdown output | |
35 | * Can prettify C as well as Lua code with built-in prettifier | |
36 | * lfs and lpeg references understood | |
37 | * 'pale' template available | |
38 | * multiple return groups | |
39 | * experimental `@error` tag | |
40 | * Moonscript and plain C support | |
41 | ||
42 | ||
43 | ### Fixes | |
44 | ||
45 | * works with non-compatibily Lua 5.2, including `markdown.lua` | |
46 | * module names can not be types | |
47 | * all `builtin` Lua files are requirable without `module` | |
48 | * backticks expand in copyright and other 'info' tabs | |
49 | * `-m` tries harder to resolve methods | |
50 | * auto-scroll in navigation area to avoid breaking identifiers | |
51 | * better error message for non-luadoc-compatible behaviour | |
52 | * custom see references fixed | |
53 | ||
54 | ||
55 | ||
0 | ## Version 1.4.3 | |
1 | ||
2 | ### Features | |
3 | ||
4 | * @include tag for including Markdown documentation file directly into module docstring | |
5 | * `prettify_files` makes per-item links to prettified source. | |
6 | * link targets rendered in bright yellow to make referenced functions more obvious | |
7 | * add update time to footer of page | |
8 | * better C support: `global_lookup=true` - invoked when `parse_extra={C=true}` | |
9 | * `kind_names` can override names used in sidebar | |
10 | ||
11 | ### Fixes | |
12 | ||
13 | * `all=true` in `config.ld` did not work. | |
14 | * `dont_escape_underscore` logic fixed: do not use in prettified code blocks | |
15 | * check that `ldoc` config exists before checking field values | |
16 | * annotation rendering fixed | |
17 | * summary not dropped when using `type` sections | |
18 | * directory as argument case was broken | |
19 | * parameter names which were List methods causing mayhem | |
20 | * files are processed in fixed order across platforms | |
21 | ||
22 | ## Version 1.4.2 | |
23 | ||
24 | ### Features | |
25 | ||
26 | * Can define fields/properties of objects; `readonly` modifier supported (#93) | |
27 | * Can switch off auto-linking to Lua manual with `no_lua_ref` | |
28 | * Module sorting is off by default, use `sort_modules=true` | |
29 | * References to 'classes' now work properly | |
30 | * Option to use first Markdown title instead of file names with `use_markdown_titles` | |
31 | * Automatic `Metamethods` and `Methods` sections generated for `classmod` classes | |
32 | * `unqualified=true` to strip package names on sidebar (#110) | |
33 | * Custom tags (which may be hidden) | |
34 | * Custom Display Name handlers | |
35 | ||
36 | ### Fixes | |
37 | ||
38 | * stricter about doc comments, now excludes common '----- XXXXX ----' pattern | |
39 | * no longer expects space after `##` in Markdown (#96) | |
40 | * Section lookup was broken | |
41 | * With `export` tag, decide whether method is static or not | |
42 | * `classmod` classes now respect custom sections (#113) | |
43 | * Minor issues with prettification | |
44 | * Command-line flags set explicitly take precendence over configuration file values. | |
45 | * Boilerplate Lua block comment ignored properly (#137) | |
46 | * Inline links with underscores sorted (#22) | |
47 | * Info section ordering is now consistent (#150) | |
48 | ||
49 | ## Version 1.4.0 | |
50 | ||
51 | ### Features | |
52 | ||
53 | * `sort=true` to sort items within sections alphabetically | |
54 | * `@set` tag in module comments; e.g, can say `@set sort=true` | |
55 | * `@classmod` tag for defining modules that export one class | |
56 | * can generate Markdown output | |
57 | * Can prettify C as well as Lua code with built-in prettifier | |
58 | * lfs and lpeg references understood | |
59 | * 'pale' template available | |
60 | * multiple return groups | |
61 | * experimental `@error` tag | |
62 | * Moonscript and plain C support | |
63 | ||
64 | ||
65 | ### Fixes | |
66 | ||
67 | * works with non-compatibily Lua 5.2, including `markdown.lua` | |
68 | * module names can not be types | |
69 | * all `builtin` Lua files are requirable without `module` | |
70 | * backticks expand in copyright and other 'info' tabs | |
71 | * `-m` tries harder to resolve methods | |
72 | * auto-scroll in navigation area to avoid breaking identifiers | |
73 | * better error message for non-luadoc-compatible behaviour | |
74 | * custom see references fixed | |
75 | ||
76 | ||
77 |
16 | 16 | |
17 | 17 | Otherwise, the output is very similar, which is no accident since the HTML templates are |
18 | 18 | based directly on LuaDoc. You can ship your own customized templates and style sheets with |
19 | your [own project](http://nilnor.github.com/textui/docs/), however. You have an option to | |
20 | use Markdown to process the documentation, which means no ugly HTML is needed in doc | |
21 | comments. C/C++ extension modules may be documented in a similar way, although function | |
19 | your [own project](http://nilnor.github.com/textui/docs/) (also see Graham Hannington's | |
20 | documentation for [Lua for z/OS](lua4z.com/doc/)). LDoc comes with three extra themes; 'pale' | |
21 | for those who like whitespace, 'one' for one-column output, and 'fixed' for a fixed navigation | |
22 | bar down the left side. | |
23 | ||
24 | You have an option to use Markdown to process the documentation, which means no ugly HTML | |
25 | is needed in doc comments. | |
26 | C/C++ extension modules may be documented in a similar way, although function | |
22 | 27 | names cannot be inferred from the code itself. |
23 | 28 | |
24 | 29 | LDoc can provide integrated documentation, with traditional function comments, any documents |
142 | 147 | You can also give the function name itself as an explicit tag, |
143 | 148 | which is especially useful when documenting a Lua api exported by C code: |
144 | 149 | |
145 | /// A C function which is exported to Lua with another name, | |
146 | // because the ways of C can be mysterious! | |
147 | // @function our_nice_function | |
148 | int _some_function_for_lua(lua_State* l) { | |
149 | .... | |
150 | } | |
150 | ```C | |
151 | /// A C function which is exported to Lua with another name, | |
152 | // because the ways of C can be mysterious! | |
153 | // @function our_nice_function | |
154 | int _some_function_for_lua(lua_State* l) { | |
155 | .... | |
156 | } | |
157 | ``` | |
151 | 158 | |
152 | 159 | The tags basically add all the detail that cannot be derived from the source code |
153 | 160 | automatically. |
188 | 195 | end |
189 | 196 | |
190 | 197 | ... |
191 | Of course there is also the 'module' tag which you have already seen. | |
192 | 198 | |
193 | 199 | #### Tables and constant values (fields) |
194 | 200 | |
215 | 221 | |
216 | 222 | The rule followed here is `NAME = <table-constructor>`. If LDoc can't work out the name and |
217 | 223 | type from the following code, then a warning will be issued, pointing to the file and |
218 | location. | |
224 | location. Only single-level tables are currently supported, and the fields must be valid | |
225 | identifiers. | |
219 | 226 | |
220 | 227 | Another kind of module-level type is 'field', such as follows: |
221 | 228 | |
238 | 245 | ... |
239 | 246 | end |
240 | 247 | |
241 | As mentioned before, this is often especially useful in C where things | |
242 | may look different in the C code than they will in the final Lua api which | |
243 | you want to document. | |
248 | This is especially useful in C where the function declarations | |
249 | are different from final Lua api which you are documenting. | |
244 | 250 | |
245 | 251 | ### Doing modules the Lua 5.1 way |
246 | 252 | |
292 | 298 | ### Local functions |
293 | 299 | |
294 | 300 | Apart from exported functions, a module usually contains local functions. By default, LDoc |
295 | does not include these in the documentation, but they can be enabled using the `--all` flag. | |
301 | does not include these in the documentation, but they can be enabled using the `--all` flag, | |
302 | or `all=true` in `config.ld`. | |
296 | 303 | They can be documented just like 'public' functions: |
297 | 304 | |
298 | 305 | --- it's clear that boo is local from context. |
388 | 395 | ------ |
389 | 396 | -- extract standard variables. |
390 | 397 | -- @param s the string |
391 | -- @return @{\stdvars} | |
398 | -- @return @{\\stdvars} | |
392 | 399 | function extract_std(s) ... end |
393 | 400 | |
394 | 401 | ------ |
395 | 402 | -- standard variables. |
396 | -- Use @{\extract_std} to parse a string containing variables, | |
397 | -- and @{\pack_std} to make such a string. | |
403 | -- Use @{\\extract_std} to parse a string containing variables, | |
404 | -- and @{\\pack_std} to make such a string. | |
398 | 405 | -- @field length |
399 | 406 | -- @field duration |
400 | 407 | -- @field viscosity |
405 | 412 | The link text can be changed from the default by the extended syntax `@{\ref|text}. |
406 | 413 | |
407 | 414 | You can also put references in backticks, like `\`stdvars\``. This is commonly used in |
408 | Markdown to indicate code, so it comes naturally when writing documents. It is controlled by | |
409 | the configuration variable `backtick_references` or the `backtick` format; | |
415 | Markdown to indicate code, so it comes naturally when writing documents. The difference | |
416 | is that the backticked expression does not have to be a reference and then will appear | |
417 | in code style; with @ references you will get a warning for unrecognized symbols | |
418 | and the result will be rendered as '???'. | |
419 | ||
420 | It is controlled by the configuration variable `backtick_references` or the `backtick` format; | |
410 | 421 | the default is `true` if you use Markdown in your project, but can be specified explicitly |
411 | 422 | in `config.ld`. |
412 | 423 | |
660 | 671 | B = 2; -- beta |
661 | 672 | } |
662 | 673 | |
663 | Simularly, function parameter comments can be directly used: | |
674 | Similarly, function parameter comments can be directly used: | |
664 | 675 | |
665 | 676 | ------------ |
666 | 677 | -- third function. Can also provide parameter comments inline, |
767 | 778 | and descriptions; you can also use the `-f` flag. This requires a markdown processor. |
768 | 779 | LDoc knows how to use: |
769 | 780 | |
770 | - [markdown.lua](http://www.frykholm.se/files/markdown.lua) a pure Lua processor by | |
781 | - [markdown.lua](http://www.frykholm.se/files/markdown.lua) a pure Lua processor by | |
771 | 782 | Niklas Frykholm. For convenience, LDoc comes with a copy of markdown.lua. |
772 | 783 | - [lua-discount](http://asbradbury.org/projects/lua-discount/), a faster alternative |
773 | 784 | (installed with `luarocks install lua-discount`). lua-discount uses the C |
783 | 794 | |
784 | 795 | Even with the default of 'plain' some minimal processing takes place, in particular empty lines |
785 | 796 | are treated as line breaks. If the 'backticks' formatter is used, then it's equivalent to |
786 | using 'process_backticks=true` in `config.ld` and backticks will be | |
797 | using `process_backticks=true` in `config.ld` and backticks will be | |
787 | 798 | expanded into documentation links like `@{\ref}` and converted into `<code>ref</code>` |
788 | 799 | otherwise. |
789 | 800 | |
943 | 954 | will give a _one-column_ layout, which can be easier to use as a programming reference. You |
944 | 955 | can suppress the contents summary with `no_summary`. |
945 | 956 | |
957 | If you don't like the usual top-level names, like 'Module' and 'Topics', you can override these | |
958 | with `kind_names` in `config.ld`. For instance, in Penlight I use `kind_names={topic='Manual',module='Libraries'}` | |
959 | ||
946 | 960 | ## Customizing the Page |
947 | 961 | |
948 | 962 | A basic customization is to override the default UTF-8 encoding using `charset`. For instance, |
1010 | 1024 | [lxsh](https://github.com/xolox/lua-lxsh) |
1011 | 1025 | can be used (available from LuaRocks) if you want something more powerful. `pretty='lxsh'` will |
1012 | 1026 | cause `lxsh` to be used, if available. |
1027 | ||
1028 | Sometimes the best examples you have are your source files. `prettify_files=true` will prettify | |
1029 | all sources, and generate per-function links to the source. | |
1013 | 1030 | |
1014 | 1031 | ## Readme files |
1015 | 1032 | |
1115 | 1132 | possible to use type aliases like **@string** to describe fields, since they will expand to |
1116 | 1133 | 'param'. |
1117 | 1134 | |
1135 | ||
1118 | 1136 | Another modifier understood by LDoc is `opt`. For instance, |
1119 | 1137 | |
1120 | 1138 | ---- testing [opt] |
1122 | 1140 | -- @param[opt] two |
1123 | 1141 | -- @param three |
1124 | 1142 | -- @param[opt] four |
1125 | function two (one,two,three,four) | |
1143 | function fun (one,two,three,four) | |
1126 | 1144 | end |
1127 | ----> displayed as: two (one [, two], three [, four]) | |
1128 | ||
1129 | This modifier can also be used with type aliases. If a value is given for `opt` | |
1130 | then LDoc can present this as the default value for this optional argument. | |
1145 | ----> displayed as: fun (one [, two], three [, four]) | |
1146 | ||
1147 | A more typical Lua API would have a chain of optional arguments, like so: | |
1148 | ||
1149 | ---- a chain of options | |
1150 | -- @param one | |
1151 | -- @param[opt] two | |
1152 | -- @param[optchain] three | |
1153 | -- @param[optchain] four | |
1154 | function fun (one,two,three,four) | |
1155 | end | |
1156 | ----> displayed as: fun (one [, two [, three [, four]]]) | |
1157 | ||
1158 | This is a bit tedious to type, so the rule is that a series of 'opt' modifiers will be interpreted | |
1159 | as 'opt','optchain'.... . If you want to be explicit, then do `convert_opt=true` in your | |
1160 | `config.ld`. | |
1161 | ||
1162 | If a value is given for `opt`then LDoc can present this as the default value for this optional argument. | |
1163 | ||
1164 | This modifier can also be used with typed param aliases. | |
1131 | 1165 | |
1132 | 1166 | --- a function with typed args. |
1133 | 1167 | -- If the Lua function has varargs, then |
1140 | 1174 | function one (name,age,...) |
1141 | 1175 | end |
1142 | 1176 | ----> displayed as: one (name, age [, calender='gregorian' [, offset=0]]) |
1143 | ||
1144 | 1177 | |
1145 | 1178 | (See @{four.lua}, rendered [here](http://stevedonovan.github.io/ldoc/examples/four)) |
1146 | 1179 | |
1203 | 1236 | - `examples` a directory or file: can be a table |
1204 | 1237 | - `readme` or `topics` readme files (to be processed with Markdown) |
1205 | 1238 | - `pretty` code prettify 'lua' (default) or 'lxsh' |
1239 | - `prettify_files` prettify the source as well and make links to it; if its value is "show" | |
1240 | then also index the source files. | |
1206 | 1241 | - `charset` use if you want to override the UTF-8 default (also **@charset** in files) |
1207 | 1242 | - `sort` set if you want all items in alphabetical order |
1208 | 1243 | - `no_return_or_parms` don't show parameters or return values in output |
1244 | - `no_lua_ref` stop obsessively trying to create references to standard Lua libraries | |
1209 | 1245 | - `backtick_references` whether references in backticks will be resolved. Happens by default |
1210 | 1246 | when using Markdown. When explicit will expand non-references in backticks into `<code>` elements |
1211 | 1247 | - `plain` set to true if `format` is set but you don't want code comments processed |
1212 | - `wrap` ?? | |
1248 | - `wrap` set to true if you want to allow long names to wrap in the summaries | |
1213 | 1249 | - `manual_url` point to an alternative or local location for the Lua manual, e.g. |
1214 | 1250 | 'file:///D:/dev/lua/projects/lua-5.1.4/doc/manual.html' |
1215 | 1251 | - `no_summary` suppress the Contents summary |
1252 | - `custom_tags` define some new tags, which will be presented after the function description. | |
1253 | The format is `{<name>,[title=<name>,}{hidden=false,}{format=nil}}`. For instance | |
1254 | `custom_tags={'remark',title='Remarks'}` will add a little `Remarks` section to the docs for any function | |
1255 | containing this tag. `format` can be a function - if not present the default formatter will be used, | |
1256 | e.g. Markdown | |
1216 | 1257 | - `custom_see_handler` function that filters see-references |
1217 | 1258 | - `custom_display_name_handler` function that formats an item's name. The arguments are the item |
1218 | 1259 | and the default function used to format the name. For example, to show an icon or label beside any |
1219 | 1260 | function tagged with a certain tag: |
1261 | ||
1220 | 1262 | -- define a @callback tag: |
1221 | 1263 | custom_tags = { { 'callback', hidden = true } } |
1222 | 1264 | |
1230 | 1272 | |
1231 | 1273 | - `not_luadoc` set to `true` if the docs break LuaDoc compatibility |
1232 | 1274 | - `no_space_before_args` set to `true` if you do not want a space between a function's name and its arguments. |
1233 | - `template_escape` overrides the usual '#' used for Lua code in templates. This needs to be changed if the output format is Markdown, for instance. | |
1275 | - `template_escape` overrides the usual '#' used for Lua code in templates. | |
1276 | This needs to be changed if the output format is Markdown, for instance. | |
1234 | 1277 | |
1235 | 1278 | _Available functions are:_ |
1236 | 1279 | |
1310 | 1353 | emphasizing parameter names). The narrative alone _can_ to be sufficient, if it is written |
1311 | 1354 | well. |
1312 | 1355 | |
1313 | There are two other stylesheets available in LDoc since 1.4; the first is `ldoc_one.css` which is what | |
1356 | There are three other stylesheets available in LDoc since 1.4; the first is `ldoc_one.css` which is what | |
1314 | 1357 | you get from `one=true` and the second is `ldoc_pale.css`. This is a lighter theme which |
1315 | 1358 | might give some relief from the heavier colours of the default. You can use this style with |
1316 | 1359 | `style="!pale"` or `-s !pale`. |
1317 | 1360 | See the [Lake](http://stevedonovan.github.io/lake/modules/lakelibs.html) documentation |
1318 | as an example of its use. | |
1361 | as an example of its use. With 1.4.3 there is also the `style='!fixed'` where the | |
1362 | left navigation panel is fixed and does not scroll with the rest of the document; | |
1363 | you may find this assists navigation in complex modules and documents. | |
1319 | 1364 | |
1320 | 1365 | Of course, there's no reason why LDoc must always generate HTML. `--ext` defines what output |
1321 | 1366 | extension to use; this can also be set in the configuration file. So it's possible to write |
72 | 72 | globals.set_manual_url 'http://www.lua.org/manual/5.1/manual.html' |
73 | 73 | end |
74 | 74 | |
75 | local file_methods = { | |
76 | close = true, | |
77 | flush = true, | |
78 | lines = true, | |
79 | read = true, | |
80 | seek = true, | |
81 | setvbuf = true, | |
82 | write = true, | |
83 | } | |
84 | ||
75 | 85 | -- external libs tracked by LDoc using LDoc style |
76 | 86 | local xlibs = { |
77 | 87 | lfs='lfs.html', lpeg='lpeg.html', |
89 | 99 | return nil |
90 | 100 | end |
91 | 101 | end |
92 | if tables[tbl] then -- function inside standard Lua table | |
102 | if tbl == 'file' then -- special case: file objects! | |
103 | if not file_methods[name] then | |
104 | return nil | |
105 | end | |
106 | name = 'file:'..name | |
107 | href = fun_ref..name | |
108 | elseif tables[tbl] then -- function inside standard Lua table | |
93 | 109 | local t = rawget(_G,tbl) -- do a quick sanity check |
94 | 110 | if not rawget(t,name) then |
95 | 111 | return nil |
15 | 15 | |
16 | 16 | -- these are the basic tags known to ldoc. They come in several varieties: |
17 | 17 | -- - 'M' tags with multiple values like 'param' (TAG_MULTI) |
18 | -- - 'ML' tags which have a single multi-lined value like 'usage' (TAG_MULTI_LINE) | |
18 | 19 | -- - 'id' tags which are identifiers, like 'name' (TAG_ID) |
19 | 20 | -- - 'S' tags with a single value, like 'release' (TAG_SINGLE) |
20 | 21 | -- - 'N' tags which have no associated value, like 'local` (TAG_FLAG) |
24 | 25 | class = 'id', name = 'id', pragma = 'id', alias = 'id', within = 'id', |
25 | 26 | copyright = 'S', summary = 'S', description = 'S', release = 'S', license = 'S', |
26 | 27 | fixme = 'S', todo = 'S', warning = 'S', raise = 'S', charset = 'S', |
27 | ['local'] = 'N', export = 'N', private = 'N', constructor = 'N', static = 'N'; | |
28 | ['local'] = 'N', export = 'N', private = 'N', constructor = 'N', static = 'N',include = 'S', | |
28 | 29 | -- project-level |
29 | module = 'T', script = 'T', example = 'T', topic = 'T', submodule='T', classmod='T', | |
30 | module = 'T', script = 'T', example = 'T', topic = 'T', submodule='T', classmod='T', file='T', | |
30 | 31 | -- module-level |
31 | 32 | ['function'] = 'T', lfunction = 'T', table = 'T', section = 'T', type = 'T', |
32 | 33 | annotation = 'T', factory = 'T'; |
40 | 41 | topic = true, |
41 | 42 | submodule = true, |
42 | 43 | classmod = true, |
44 | file = true, | |
43 | 45 | } |
44 | 46 | |
45 | 47 | known_tags._code_types = { |
132 | 134 | local item_name = last_item.tags.name |
133 | 135 | for tag, value in pairs(tags) do |
134 | 136 | if known_tags._annotation_tags[tag] then |
137 | tags.summary = nil | |
135 | 138 | tags:add('class','annotation') |
136 | 139 | tags:add('summary',value) |
137 | 140 | tags:add('name',item_name..'-'..tag..acount) |
236 | 239 | elseif doc.project_level(item.type) then |
237 | 240 | this_mod = item |
238 | 241 | local package,mname,submodule |
239 | if item.type == 'module' then | |
242 | if item.type == 'module' or item.type == 'classmod' then | |
240 | 243 | -- if name is 'package.mod', then mod_name is 'mod' |
241 | 244 | package,mname = split_dotted_name(this_mod.name) |
242 | 245 | if self.args.merge then |
286 | 289 | else |
287 | 290 | display_name = summary |
288 | 291 | lookup_name = summary |
292 | item.summary = '' | |
289 | 293 | end |
290 | 294 | item.display_name = display_name |
291 | 295 | this_mod.section = item |
367 | 371 | end |
368 | 372 | end |
369 | 373 | if this_section then |
370 | section_description = this_section.summary..' '..(this_section.description or '') | |
371 | this_section.summary = '' | |
374 | --section_description = this_section.summary..' '..(this_section.description or '') | |
375 | --this_section.summary = '' | |
372 | 376 | elseif item.tags.within then |
373 | section_description = item.tags.within | |
374 | item.section = section_description | |
377 | item.section = item.tags.within | |
375 | 378 | else |
376 | 379 | if item.type == 'function' or item.type == 'lfunction' then |
377 | 380 | section_description = "Methods" |
379 | 382 | item.section = item.type |
380 | 383 | end |
381 | 384 | elseif item.tags.within then -- ad-hoc section... |
382 | section_description = item.tags.within | |
383 | item.section = section_description | |
385 | item.section = item.tags.within | |
384 | 386 | else -- otherwise, just goes into the default sections (Functions,Tables,etc) |
385 | 387 | item.section = item.type; |
386 | 388 | end |
724 | 726 | local original_names = formal and formal or param_names |
725 | 727 | local names = List() |
726 | 728 | self.subparams = {} |
729 | params.map = {} | |
730 | ||
727 | 731 | for i,name in ipairs(original_names) do |
728 | 732 | if type(name) ~= 'string' then |
729 | 733 | self:error("declared table cannot have array entries") |
741 | 745 | fields = nil |
742 | 746 | end |
743 | 747 | |
744 | params[name] = comments[i] | |
748 | params.map[name] = comments[i] | |
745 | 749 | if pmods then |
746 | 750 | pmods[name] = pmods[i] |
747 | 751 | end |
803 | 807 | -- with @param[opt] b |
804 | 808 | local buffer, npending = { }, 0 |
805 | 809 | local function acc(x) table.insert(buffer, x) end |
806 | -- a number of trailing [opt]s can be safely converted to [opt],[optchain],... | |
807 | if pmods then | |
810 | -- a number of trailing [opt]s will be usually converted to [opt],[optchain],... | |
811 | -- *unless* a person uses convert_opt. | |
812 | if pmods and not doc.ldoc.convert_opt then | |
808 | 813 | local m = pmods[#names] |
809 | 814 | if m and m.opt then |
810 | 815 | m.optchain = m.opt |
851 | 856 | return mparam and mparam.type or '' |
852 | 857 | end |
853 | 858 | |
859 | -- default value for param; if optional but no default, it's just `true`. | |
854 | 860 | function Item:default_of_param(p) |
855 | 861 | local m = self:param_modifiers(p) |
856 | 862 | if not m then return nil end |
857 | 863 | local opt = m.optchain or m.opt |
858 | if opt == true then return nil end | |
859 | 864 | return opt |
860 | 865 | end |
861 | 866 | |
1098 | 1103 | lua_manual_ref = function(s) return false end |
1099 | 1104 | else |
1100 | 1105 | lua_manual_ref = global.lua_manual_ref |
1106 | end | |
1107 | -- pure C projects use global lookup (no namespaces) | |
1108 | if ldoc and ldoc.global_lookup == nil then | |
1109 | local using_c = ldoc.parse_extra and ldoc.parse_extra.C | |
1110 | ldoc.global_lookup = using_c or false | |
1101 | 1111 | end |
1102 | 1112 | |
1103 | 1113 | -- is this a fully qualified module name? |
1141 | 1151 | end |
1142 | 1152 | end |
1143 | 1153 | else -- plain jane name; module in this package, function in this module |
1154 | if ldoc and ldoc.global_lookup then | |
1155 | for m in modules:iter() do | |
1156 | fun_ref = m:get_fun_ref(s) | |
1157 | if fun_ref then return reference(s,m,fun_ref) end | |
1158 | end | |
1159 | return nil,"function: "..s.." not found globally" | |
1160 | end | |
1144 | 1161 | mod_ref = modules.by_name[self.package..'.'..s] |
1145 | 1162 | if ismod(mod_ref) then return reference(s, mod_ref,nil) end |
1146 | 1163 | fun_ref = self:get_fun_ref(s) |
1263 | 1280 | if #self.params > 0 then |
1264 | 1281 | print 'parameters:' |
1265 | 1282 | for _,p in ipairs(self.params) do |
1266 | print('',p,self.params[p]) | |
1283 | print('',p,self.params.map[p]) | |
1267 | 1284 | end |
1268 | 1285 | end |
1269 | 1286 | if self.ret and #self.ret > 0 then |
71 | 71 | background-color: #ffffff; margin: 0px; |
72 | 72 | } |
73 | 73 | |
74 | code, tt { font-family: monospace; } | |
74 | code, tt { font-family: monospace; font-size: 1.1em; } | |
75 | 75 | span.parameter { font-family:monospace; } |
76 | 76 | span.parameter:after { content:":"; } |
77 | 77 | span.types:before { content:"("; } |
159 | 159 | |
160 | 160 | #navigation { |
161 | 161 | float: left; |
162 | width: 18em; | |
162 | width: 14em; | |
163 | 163 | vertical-align: top; |
164 | 164 | background-color: #f0f0f0; |
165 | 165 | overflow: visible; |
193 | 193 | } |
194 | 194 | |
195 | 195 | #content { |
196 | margin-left: 18em; | |
196 | margin-left: 14em; | |
197 | 197 | padding: 1em; |
198 | 198 | width: 700px; |
199 | 199 | border-left: 2px solid #cccccc; |
286 | 286 | ol ol { margin-top: 0px; } |
287 | 287 | ul ol { margin-top: 0px; } |
288 | 288 | |
289 | /* make the target distinct; helps when we're navigating to a function */ | |
290 | a:target + * { | |
291 | background-color: #FF9; | |
292 | } | |
293 | ||
289 | 294 | /* styles for prettification of source */ |
290 | 295 | pre .comment { color: #558817; } |
291 | 296 | pre .constant { color: #a8660d; } |
292 | 297 | pre .escape { color: #844631; } |
293 | pre .keyword { color: #2239a8; font-weight: bold; } | |
298 | pre .keyword { color: #aa5050; font-weight: bold; } | |
294 | 299 | pre .library { color: #0e7c6b; } |
295 | 300 | pre .marker { color: #512b1e; background: #fedc56; font-weight: bold; } |
296 | pre .string { color: #a8660d; } | |
301 | pre .string { color: #8080ff; } | |
297 | 302 | pre .number { color: #f8660d; } |
298 | 303 | pre .operator { color: #2239a8; font-weight: bold; } |
299 | 304 | pre .preprocessor, pre .prepro { color: #a33243; } |
0 | return [[ | |
1 | /* BEGIN RESET | |
2 | ||
3 | Copyright (c) 2010, Yahoo! Inc. All rights reserved. | |
4 | Code licensed under the BSD License: | |
5 | http://developer.yahoo.com/yui/license.html | |
6 | version: 2.8.2r1 | |
7 | */ | |
8 | html { | |
9 | color: #000; | |
10 | background: #FFF; | |
11 | } | |
12 | body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,code,form,fieldset,legend,input,button,textarea,p,blockquote,th,td { | |
13 | margin: 0; | |
14 | padding: 0; | |
15 | } | |
16 | table { | |
17 | border-collapse: collapse; | |
18 | border-spacing: 0; | |
19 | } | |
20 | fieldset,img { | |
21 | border: 0; | |
22 | } | |
23 | address,caption,cite,code,dfn,em,strong,th,var,optgroup { | |
24 | font-style: inherit; | |
25 | font-weight: inherit; | |
26 | } | |
27 | del,ins { | |
28 | text-decoration: none; | |
29 | } | |
30 | li { | |
31 | list-style: bullet; | |
32 | margin-left: 20px; | |
33 | } | |
34 | caption,th { | |
35 | text-align: left; | |
36 | } | |
37 | h1,h2,h3,h4,h5,h6 { | |
38 | font-size: 100%; | |
39 | font-weight: bold; | |
40 | } | |
41 | q:before,q:after { | |
42 | content: ''; | |
43 | } | |
44 | abbr,acronym { | |
45 | border: 0; | |
46 | font-variant: normal; | |
47 | } | |
48 | sup { | |
49 | vertical-align: baseline; | |
50 | } | |
51 | sub { | |
52 | vertical-align: baseline; | |
53 | } | |
54 | legend { | |
55 | color: #000; | |
56 | } | |
57 | input,button,textarea,select,optgroup,option { | |
58 | font-family: inherit; | |
59 | font-size: inherit; | |
60 | font-style: inherit; | |
61 | font-weight: inherit; | |
62 | } | |
63 | input,button,textarea,select {*font-size:100%; | |
64 | } | |
65 | /* END RESET */ | |
66 | ||
67 | body { | |
68 | margin-left: 1em; | |
69 | margin-right: 1em; | |
70 | font-family: arial, helvetica, geneva, sans-serif; | |
71 | background-color: #ffffff; margin: 0px; | |
72 | } | |
73 | ||
74 | code, tt { font-family: monospace; font-size: 1.1em; } | |
75 | span.parameter { font-family:monospace; } | |
76 | span.parameter:after { content:":"; } | |
77 | span.types:before { content:"("; } | |
78 | span.types:after { content:")"; } | |
79 | .type { font-weight: bold; font-style:italic } | |
80 | ||
81 | body, p, td, th { font-size: .95em; line-height: 1.2em;} | |
82 | ||
83 | p, ul { margin: 10px 0 0 0px;} | |
84 | ||
85 | strong { font-weight: bold;} | |
86 | ||
87 | em { font-style: italic;} | |
88 | ||
89 | h1 { | |
90 | font-size: 1.5em; | |
91 | margin: 0 0 20px 0; | |
92 | } | |
93 | h2, h3, h4 { margin: 15px 0 10px 0; } | |
94 | h2 { font-size: 1.25em; } | |
95 | h3 { font-size: 1.15em; } | |
96 | h4 { font-size: 1.06em; } | |
97 | ||
98 | a:link { font-weight: bold; color: #004080; text-decoration: none; } | |
99 | a:visited { font-weight: bold; color: #006699; text-decoration: none; } | |
100 | a:link:hover { text-decoration: underline; } | |
101 | ||
102 | hr { | |
103 | color:#cccccc; | |
104 | background: #00007f; | |
105 | height: 1px; | |
106 | } | |
107 | ||
108 | blockquote { margin-left: 3em; } | |
109 | ||
110 | ul { list-style-type: disc; } | |
111 | ||
112 | p.name { | |
113 | font-family: "Andale Mono", monospace; | |
114 | padding-top: 1em; | |
115 | } | |
116 | ||
117 | pre.example { | |
118 | background-color: rgb(245, 245, 245); | |
119 | border: 1px solid silver; | |
120 | padding: 10px; | |
121 | margin: 10px 0 10px 0; | |
122 | font-family: "Andale Mono", monospace; | |
123 | font-size: .85em; | |
124 | } | |
125 | ||
126 | pre { | |
127 | background-color: rgb(245,245,255); // rgb(245, 245, 245); | |
128 | border: 1px solid #cccccc; //silver; | |
129 | padding: 10px; | |
130 | margin: 10px 0 10px 0; | |
131 | overflow: auto; | |
132 | font-family: "Andale Mono", monospace; | |
133 | } | |
134 | ||
135 | ||
136 | table.index { border: 1px #00007f; } | |
137 | table.index td { text-align: left; vertical-align: top; } | |
138 | ||
139 | #container { | |
140 | margin-left: 1em; | |
141 | margin-right: 1em; | |
142 | background-color: #ffffff; | |
143 | } | |
144 | ||
145 | #product { | |
146 | text-align: center; | |
147 | border-bottom: 1px solid #cccccc; | |
148 | background-color: #ffffff; | |
149 | } | |
150 | ||
151 | #product big { | |
152 | font-size: 2em; | |
153 | } | |
154 | ||
155 | #main { | |
156 | background-color:#FFFFFF; // #f0f0f0; | |
157 | border-left: 1px solid #cccccc; | |
158 | } | |
159 | ||
160 | #navigation { | |
161 | position: fixed; | |
162 | top: 0; | |
163 | left: 0; | |
164 | float: left; | |
165 | width: 14em; | |
166 | vertical-align: top; | |
167 | background-color:#FFFFFF; // #f0f0f0; | |
168 | border-right: 2px solid #cccccc; | |
169 | overflow: visible; | |
170 | overflow-y: scroll; | |
171 | height: 100%; | |
172 | padding-left: 1em; | |
173 | } | |
174 | ||
175 | #navigation h2 { | |
176 | background-color:#FFFFFF;//:#e7e7e7; | |
177 | font-size:1.1em; | |
178 | color:#000000; | |
179 | text-align: left; | |
180 | padding:0.2em; | |
181 | border-bottom:1px solid #dddddd; | |
182 | } | |
183 | ||
184 | #navigation ul | |
185 | { | |
186 | font-size:1em; | |
187 | list-style-type: none; | |
188 | margin: 1px 1px 10px 1px; | |
189 | } | |
190 | ||
191 | #navigation li { | |
192 | text-indent: -1em; | |
193 | display: block; | |
194 | margin: 3px 0px 0px 22px; | |
195 | } | |
196 | ||
197 | #navigation li li a { | |
198 | margin: 0px 3px 0px -1em; | |
199 | } | |
200 | ||
201 | #content { | |
202 | margin-left: 14em; | |
203 | padding: 1em; | |
204 | padding-left: 2em; | |
205 | width: 700px; | |
206 | border-left: 2px solid #cccccc; | |
207 | // border-right: 2px solid #cccccc; | |
208 | background-color: #ffffff; | |
209 | } | |
210 | ||
211 | #about { | |
212 | clear: both; | |
213 | padding-left: 1em; | |
214 | margin-left: 14em; // avoid the damn sidebar! | |
215 | border-top: 2px solid #cccccc; | |
216 | border-left: 2px solid #cccccc; | |
217 | background-color: #ffffff; | |
218 | } | |
219 | ||
220 | @media print { | |
221 | body { | |
222 | font: 12pt "Times New Roman", "TimeNR", Times, serif; | |
223 | } | |
224 | a { font-weight: bold; color: #004080; text-decoration: underline; } | |
225 | ||
226 | #main { | |
227 | background-color: #ffffff; | |
228 | border-left: 0px; | |
229 | } | |
230 | ||
231 | #container { | |
232 | margin-left: 2%; | |
233 | margin-right: 2%; | |
234 | background-color: #ffffff; | |
235 | } | |
236 | ||
237 | #content { | |
238 | padding: 1em; | |
239 | background-color: #ffffff; | |
240 | } | |
241 | ||
242 | #navigation { | |
243 | display: none; | |
244 | } | |
245 | pre.example { | |
246 | font-family: "Andale Mono", monospace; | |
247 | font-size: 10pt; | |
248 | page-break-inside: avoid; | |
249 | } | |
250 | } | |
251 | ||
252 | table.module_list { | |
253 | border-width: 1px; | |
254 | border-style: solid; | |
255 | border-color: #cccccc; | |
256 | border-collapse: collapse; | |
257 | } | |
258 | table.module_list td { | |
259 | border-width: 1px; | |
260 | padding: 3px; | |
261 | border-style: solid; | |
262 | border-color: #cccccc; | |
263 | } | |
264 | table.module_list td.name { background-color: #f0f0f0; ; min-width: 200px; } | |
265 | table.module_list td.summary { width: 100%; } | |
266 | ||
267 | table.function_list { | |
268 | border-width: 1px; | |
269 | border-style: solid; | |
270 | border-color: #cccccc; | |
271 | border-collapse: collapse; | |
272 | } | |
273 | table.function_list td { | |
274 | border-width: 1px; | |
275 | padding: 3px; | |
276 | border-style: solid; | |
277 | border-color: #cccccc; | |
278 | } | |
279 | table.function_list td.name { background-color: #f6f6ff; ; min-width: 200px; } | |
280 | table.function_list td.summary { width: 100%; } | |
281 | ||
282 | dl.table dt, dl.function dt {border-top: 1px solid #ccc; padding-top: 1em;} | |
283 | dl.table dd, dl.function dd {padding-bottom: 1em; margin: 10px 0 0 20px;} | |
284 | dl.table h3, dl.function h3 {font-size: .95em;} | |
285 | ||
286 | ul.nowrap { | |
287 | overflow:auto; | |
288 | whitespace:nowrap; | |
289 | } | |
290 | ||
291 | /* stop sublists from having initial vertical space */ | |
292 | ul ul { margin-top: 0px; } | |
293 | ol ul { margin-top: 0px; } | |
294 | ol ol { margin-top: 0px; } | |
295 | ul ol { margin-top: 0px; } | |
296 | ||
297 | /* make the target distinct; helps when we're navigating to a function */ | |
298 | a:target + * { | |
299 | background-color: #FF9; | |
300 | } | |
301 | ||
302 | /* styles for prettification of source */ | |
303 | pre .comment { color: #558817; } | |
304 | pre .constant { color: #a8660d; } | |
305 | pre .escape { color: #844631; } | |
306 | pre .keyword { color: #aa5050; font-weight: bold; } | |
307 | pre .library { color: #0e7c6b; } | |
308 | pre .marker { color: #512b1e; background: #fedc56; font-weight: bold; } | |
309 | pre .string { color: #8080ff; } | |
310 | pre .number { color: #f8660d; } | |
311 | pre .operator { color: #2239a8; font-weight: bold; } | |
312 | pre .preprocessor, pre .prepro { color: #a33243; } | |
313 | pre .global { color: #800080; } | |
314 | pre .prompt { color: #558817; } | |
315 | pre .url { color: #272fc2; text-decoration: underline; } | |
316 | ]] |
62 | 62 | # -------- contents of project ---------- |
63 | 63 | # local this_mod = module and module.name |
64 | 64 | # for kind, mods, type in ldoc.kinds() do |
65 | # if not ldoc.kinds_allowed or ldoc.kinds_allowed[type] then | |
65 | # if ldoc.allowed_in_contents(type,module) then | |
66 | 66 | <h2>$(kind)</h2> |
67 | 67 | <ul class="$(kind=='Topics' and '' or 'nowrap'"> |
68 | 68 | # for mod in mods() do local name = ldoc.module_name(mod) |
86 | 86 | <h1>$(ldoc.module_typename(module)) <code>$(module.name)</code></h1> |
87 | 87 | <p>$(M(module.summary,module))</p> |
88 | 88 | <p>$(M(module.description,module))</p> |
89 | # if module.tags.include then | |
90 | $(M(ldoc.include_file(module.tags.include))) | |
91 | # end | |
89 | 92 | # if module.usage then |
90 | 93 | # local li,il = use_li(module.usage) |
91 | 94 | <h3>Usage:</h3> |
131 | 134 | # for kind, items in module.kinds() do |
132 | 135 | # local kitem = module.kinds:get_item(kind) |
133 | 136 | <h2><a name="$(no_spaces(kind))"></a>$(kind)</h2> |
134 | #-- $(M(module.kinds:get_section_description(kind),nil)) | |
137 | $(M(module.kinds:get_section_description(kind),nil)) | |
135 | 138 | # if kitem then |
136 | 139 | $(M(ldoc.descript(kitem),kitem)) |
137 | 140 | # if kitem.usage then |
144 | 147 | <dt> |
145 | 148 | <a name = "$(item.name)"></a> |
146 | 149 | <strong>$(display_name(item))</strong> |
150 | # if ldoc.prettify_files then | |
151 | <a style="float:right;" href="$(ldoc.source_ref(item))">line $(item.lineno)</a> | |
152 | # end | |
147 | 153 | </dt> |
148 | 154 | <dd> |
149 | 155 | $(M(ldoc.descript(item),item)) |
172 | 178 | # for parm in iter(item.params) do |
173 | 179 | # local param,sublist = item:subparam(parm) |
174 | 180 | # if sublist then |
175 | <li><span class="parameter">$(sublist)</span>$(M(item.params[sublist],item)) | |
181 | <li><span class="parameter">$(sublist)</span>$(M(item.params.map[sublist],item)) | |
176 | 182 | <ul> |
177 | 183 | # end |
178 | 184 | # for p in iter(param) do |
181 | 187 | # if tp ~= '' then |
182 | 188 | <span class="types">$(tp)</span> |
183 | 189 | # end |
184 | $(M(item.params[p],item)) | |
185 | # if def then | |
190 | $(M(item.params.map[p],item)) | |
191 | # if def == true then | |
192 | (<em>optional</em>) | |
193 | # elseif def then | |
186 | 194 | (<em>default</em> $(def)) |
187 | 195 | # end |
188 | 196 | # if item:readonly(p) then |
270 | 278 | # for m in mods() do |
271 | 279 | <tr> |
272 | 280 | <td class="name" $(nowrap)><a href="$(no_spaces(kind))/$(m.name).html">$(m.name)</a></td> |
273 | <td class="summary">$(M(m.summary,m))</td> | |
281 | <td class="summary">$(M(ldoc.strip_header(m.summary),m))</td> | |
274 | 282 | </tr> |
275 | 283 | # end -- for modules |
276 | 284 | </table> |
280 | 288 | </div> <!-- id="content" --> |
281 | 289 | </div> <!-- id="main" --> |
282 | 290 | <div id="about"> |
283 | <i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.2</a></i> | |
291 | <i>generated by <a href="http://github.com/stevedonovan/LDoc">LDoc 1.4.3</a></i> | |
292 | <i style="float:right;">Last updated $(ldoc.updatetime) </i> | |
284 | 293 | </div> <!-- id="about" --> |
285 | 294 | </div> <!-- id="container" --> |
286 | 295 | </body> |
71 | 71 | background-color: #ffffff; margin: 0px; |
72 | 72 | } |
73 | 73 | |
74 | code, tt { font-family: monospace; } | |
74 | code, tt { font-family: monospace; font-size: 1.1em; } | |
75 | 75 | |
76 | 76 | body, p, td, th { font-size: .95em; line-height: 1.2em;} |
77 | 77 | |
268 | 268 | dl.table h3, dl.function h3 {font-size: .95em;} |
269 | 269 | |
270 | 270 | /* styles for prettification of source */ |
271 | .keyword {font-weight: bold; color: #6666AA; } | |
272 | .number { color: #AA6666; } | |
273 | .string { color: #8888AA; } | |
274 | .comment { color: #666600; } | |
275 | .prepro { color: #006666; } | |
271 | pre .comment { color: #558817; } | |
272 | pre .constant { color: #a8660d; } | |
273 | pre .escape { color: #844631; } | |
274 | pre .keyword { color: #aa5050; font-weight: bold; } | |
275 | pre .library { color: #0e7c6b; } | |
276 | pre .marker { color: #512b1e; background: #fedc56; font-weight: bold; } | |
277 | pre .string { color: #8080ff; } | |
278 | pre .number { color: #f8660d; } | |
279 | pre .operator { color: #2239a8; font-weight: bold; } | |
280 | pre .preprocessor, pre .prepro { color: #a33243; } | |
281 | pre .global { color: #800080; } | |
282 | pre .prompt { color: #558817; } | |
283 | pre .url { color: #272fc2; text-decoration: underline; } | |
276 | 284 | ]==] |
70 | 70 | background-color: #ffffff; margin: 0px; |
71 | 71 | } |
72 | 72 | |
73 | code, tt { font-family: monospace; } | |
73 | code, tt { font-family: monospace; font-size: 1.1em; } | |
74 | 74 | span.parameter { font-family:monospace; } |
75 | 75 | span.parameter:after { content:":"; } |
76 | 76 | span.types:before { content:"("; } |
138 | 138 | #container { |
139 | 139 | margin-left: 1em; |
140 | 140 | margin-right: 1em; |
141 | background-color: #f0f0f0; | |
141 | background-color: #ffffff; | |
142 | 142 | } |
143 | 143 | |
144 | 144 | #product { |
161 | 161 | width: 14em; |
162 | 162 | vertical-align: top; |
163 | 163 | background-color:#FFFFFF; // #f0f0f0; |
164 | border-right: 2px solid #cccccc; | |
164 | 165 | overflow: visible; |
165 | 166 | } |
166 | 167 | |
284 | 285 | ol ol { margin-top: 0px; } |
285 | 286 | ul ol { margin-top: 0px; } |
286 | 287 | |
288 | /* make the target distinct; helps when we're navigating to a function */ | |
289 | a:target + * { | |
290 | background-color: #FF9; | |
291 | } | |
292 | ||
287 | 293 | /* styles for prettification of source */ |
288 | 294 | pre .comment { color: #558817; } |
289 | 295 | pre .constant { color: #a8660d; } |
290 | 296 | pre .escape { color: #844631; } |
291 | pre .keyword { color: #2239a8; font-weight: bold; } | |
297 | pre .keyword { color: #aa5050; font-weight: bold; } | |
292 | 298 | pre .library { color: #0e7c6b; } |
293 | 299 | pre .marker { color: #512b1e; background: #fedc56; font-weight: bold; } |
294 | pre .string { color: #a8660d; } | |
300 | pre .string { color: #8080ff; } | |
295 | 301 | pre .number { color: #f8660d; } |
296 | 302 | pre .operator { color: #2239a8; font-weight: bold; } |
297 | 303 | pre .preprocessor, pre .prepro { color: #a33243; } |
151 | 151 | end |
152 | 152 | return base..name..'.html' |
153 | 153 | end |
154 | ||
155 | function ldoc.include_file (file) | |
156 | local text,e = utils.readfile(file) | |
157 | if not text then quit("unable to include "..file) | |
158 | else | |
159 | return text | |
160 | end | |
161 | end | |
162 | ||
163 | -- these references are never from the index...? | |
164 | function ldoc.source_ref (fun) | |
165 | local modname = fun.module.name | |
166 | local pack,name = tools.split_dotted_name(modname) | |
167 | if not pack then | |
168 | name = modname | |
169 | end | |
170 | return (ldoc.single and "" or "../").."source/"..name..'.lua.html#'..fun.lineno | |
171 | end | |
154 | 172 | |
155 | 173 | function ldoc.use_li(ls) |
156 | 174 | if #ls > 1 then return '<li>','</li>' else return '','' end |
187 | 205 | |
188 | 206 | function ldoc.is_list (t) |
189 | 207 | return type(t) == 'table' and t.append |
208 | end | |
209 | ||
210 | function ldoc.strip_header (s) | |
211 | if not s then return s end | |
212 | return s:gsub('^%s*#+%s+','') | |
190 | 213 | end |
191 | 214 | |
192 | 215 | function ldoc.typename (tp) |
227 | 250 | return names |
228 | 251 | end |
229 | 252 | |
253 | -- the somewhat tangled logic that controls whether a type appears in the | |
254 | -- navigation sidebar. (At least it's no longer in the template ;)) | |
255 | function ldoc.allowed_in_contents(type,module) | |
256 | local allowed = true | |
257 | if ldoc.kinds_allowed then | |
258 | allowed = ldoc.kinds_allowed[type] | |
259 | elseif ldoc.prettify_files and type == 'file' then | |
260 | allowed = ldoc.prettify_files == 'show' or (module and module.type == 'file') | |
261 | end | |
262 | return allowed | |
263 | end | |
264 | ||
230 | 265 | local function set_charset (ldoc,m) |
231 | 266 | m = m or ldoc.module |
232 | 267 | ldoc.doc_charset = (m and m.tags.charset) or ldoc.charset |
258 | 258 | local err |
259 | 259 | f,err = utils.readfile(f) |
260 | 260 | if not f then quit(err) end |
261 | return lexer.cpp(f,{}) | |
261 | return lexer.cpp(f,{},nil,true) | |
262 | 262 | end |
263 | 263 | |
264 | 264 | function CC:grab_block_comment(v,tok) |
43 | 43 | local STRING3 = "^((['\"])%2)" -- empty string |
44 | 44 | local PREPRO = '^#.-[^\\]\n' |
45 | 45 | |
46 | local plain_matches,lua_matches,cpp_matches,lua_keyword,cpp_keyword | |
46 | local plain_matches,lua_matches,cpp_matches,cpp_matches_no_string,lua_keyword,cpp_keyword | |
47 | 47 | |
48 | 48 | local function tdump(tok) |
49 | 49 | return tok,tok |
323 | 323 | -- @param filter a table of token types to exclude, by default {space=true,comments=true} |
324 | 324 | -- @param options a table of options; by default, {number=true,string=true}, |
325 | 325 | -- which means convert numbers and strip string quotes. |
326 | function lexer.cpp(s,filter,options) | |
326 | function lexer.cpp(s,filter,options,no_string) | |
327 | 327 | filter = filter or {comments=true} |
328 | 328 | if not cpp_keyword then |
329 | 329 | cpp_keyword = { |
374 | 374 | {'^.',tdump} |
375 | 375 | } |
376 | 376 | end |
377 | return lexer.scan(s,cpp_matches,filter,options) | |
377 | if not cpp_matches_no_string then | |
378 | cpp_matches_no_string = { | |
379 | {WSPACE,wsdump}, | |
380 | {PREPRO,pdump}, | |
381 | {NUMBER3,ndump}, | |
382 | {IDEN,cpp_vdump}, | |
383 | {NUMBER4,ndump}, | |
384 | {NUMBER5,ndump}, | |
385 | {'^//.-\n',cdump}, | |
386 | {'^/%*.-%*/',cdump}, | |
387 | {'^==',tdump}, | |
388 | {'^!=',tdump}, | |
389 | {'^<=',tdump}, | |
390 | {'^>=',tdump}, | |
391 | {'^->',tdump}, | |
392 | {'^&&',tdump}, | |
393 | {'^||',tdump}, | |
394 | {'^%+%+',tdump}, | |
395 | {'^%-%-',tdump}, | |
396 | {'^%+=',tdump}, | |
397 | {'^%-=',tdump}, | |
398 | {'^%*=',tdump}, | |
399 | {'^/=',tdump}, | |
400 | {'^|=',tdump}, | |
401 | {'^%^=',tdump}, | |
402 | {'^::',tdump}, | |
403 | {'^%.%.%.',tdump}, | |
404 | {'^.',tdump} | |
405 | } | |
406 | end | |
407 | return lexer.scan(s, | |
408 | not no_string and cpp_matches or cpp_matches_no_string, | |
409 | filter,options) | |
378 | 410 | end |
379 | 411 | |
380 | 412 | --- get a list of parameters separated by a delimiter from a stream. |
13 | 13 | |
14 | 14 | -- inline <references> use same lookup as @see |
15 | 15 | local function resolve_inline_references (ldoc, txt, item, plain) |
16 | local do_escape = not plain and not ldoc.dont_escape_underscore | |
16 | 17 | local res = (txt:gsub('@{([^}]-)}',function (name) |
17 | 18 | if name:match '^\\' then return '@{'..name:sub(2)..'}' end |
18 | 19 | local qname,label = utils.splitv(name,'%s*|') |
41 | 42 | if not label then |
42 | 43 | label = ref.label |
43 | 44 | end |
44 | if not plain and label then -- a nastiness with markdown.lua and underscores | |
45 | if label and do_escape then -- a nastiness with markdown.lua and underscores | |
45 | 46 | label = label:gsub('_','\\_') |
46 | 47 | end |
47 | 48 | local html = ldoc.href(ref) or '#' |
48 | label = label or qname | |
49 | label = ldoc.escape(label or qname) | |
49 | 50 | local res = ('<a href="%s">%s</a>'):format(html,label) |
50 | 51 | return res |
51 | 52 | end)) |
52 | 53 | if backtick_references then |
53 | 54 | res = res:gsub('`([^`]+)`',function(name) |
54 | 55 | local ref,err = markup.process_reference(name) |
56 | local label = name | |
57 | if name and do_escape then | |
58 | label = name:gsub('_', '\\_') | |
59 | end | |
60 | label = ldoc.escape(label) | |
55 | 61 | if ref then |
56 | if not plain and name then | |
57 | name = name:gsub('_', '\\_') | |
58 | end | |
59 | return ('<a href="%s">%s</a> '):format(ldoc.href(ref),name) | |
62 | return ('<a href="%s">%s</a>'):format(ldoc.href(ref),label) | |
60 | 63 | else |
61 | return '<code>'..name..'</code>' | |
64 | return '<code>'..label..'</code>' | |
62 | 65 | end |
63 | 66 | end) |
64 | 67 | end |
114 | 117 | -- - insert any section ids which were generated by add_sections above |
115 | 118 | -- - prettify any code blocks |
116 | 119 | |
117 | local function process_multiline_markdown(ldoc, txt, F) | |
120 | local function process_multiline_markdown(ldoc, txt, F, filename, deflang) | |
118 | 121 | local res, L, append = {}, 0, table.insert |
119 | local filename = F.filename | |
120 | 122 | local err_item = { |
121 | 123 | warning = function (self,msg) |
122 | 124 | io.stderr:write(filename..':'..L..': '..msg,'\n') |
134 | 136 | -- If we omit the following '\n', a '--' (or '//') comment on the |
135 | 137 | -- last line won't be recognized. |
136 | 138 | code, err = prettify.code(lang,filename,code..'\n',L,false) |
139 | code = resolve_inline_references(ldoc, code, err_item,true) | |
137 | 140 | append(res,'<pre>') |
138 | 141 | append(res, code) |
139 | 142 | append(res,'</pre>') |
191 | 194 | while #code > 1 and blank(code[#code]) do -- trim blank lines. |
192 | 195 | table.remove(code) |
193 | 196 | end |
194 | pretty_code (code,'lua') | |
197 | pretty_code (code,deflang) | |
195 | 198 | else |
196 | local section = F.sections[L] | |
199 | local section = F and F.sections[L] | |
197 | 200 | if section then |
198 | 201 | append(res,('<a name="%s"></a>'):format(section)) |
199 | 202 | end |
241 | 244 | |
242 | 245 | |
243 | 246 | local function get_formatter(format) |
247 | local used_format = format | |
244 | 248 | local formatter = (formatters[format] or generic_formatter)(format) |
245 | if formatter then return formatter end | |
246 | ||
247 | for name, f in pairs(formatters) do | |
248 | formatter = f(name) | |
249 | if formatter then | |
250 | print('format: '..format..' not found, using '..name) | |
251 | return formatter | |
252 | end | |
253 | end | |
249 | if not formatter then -- try another equivalent processor | |
250 | for name, f in pairs(formatters) do | |
251 | formatter = f(name) | |
252 | if formatter then | |
253 | print('format: '..format..' not found, using '..name) | |
254 | used_format = name | |
255 | break | |
256 | end | |
257 | end | |
258 | end | |
259 | return formatter, used_format | |
254 | 260 | end |
255 | 261 | |
256 | 262 | local function text_processor(ldoc) |
273 | 279 | end |
274 | 280 | return plain_processor(txt,item) |
275 | 281 | end |
276 | if utils.is_type(item,doc.File) then | |
277 | txt = process_multiline_markdown(ldoc, txt, item) | |
282 | local is_file = utils.is_type(item,doc.File) | |
283 | local is_module = not file and item and doc.project_level(item.type) | |
284 | if is_file or is_module then | |
285 | local deflang = 'lua' | |
286 | if ldoc.parse_extra and ldoc.parse_extra.C then | |
287 | deflang = 'c' | |
288 | end | |
289 | if is_module then | |
290 | txt = process_multiline_markdown(ldoc, txt, nil, item.file.filename, deflang) | |
291 | else | |
292 | txt = process_multiline_markdown(ldoc, txt, item, item.filename, deflang) | |
293 | end | |
278 | 294 | else |
279 | 295 | txt = resolve_inline_references(ldoc, txt, item) |
280 | 296 | end |
287 | 303 | local function get_processor(ldoc, format) |
288 | 304 | if format == 'plain' then return text_processor(ldoc) end |
289 | 305 | |
290 | local formatter = get_formatter(format) | |
306 | local formatter,actual_format = get_formatter(format) | |
291 | 307 | if formatter then |
292 | 308 | markup.plain = false |
309 | -- AFAIK only markdown.lua has underscore-in-identifier problem... | |
310 | if ldoc.dont_escape_underscore ~= nil then | |
311 | ldoc.dont_escape_underscore = actual_format ~= 'markdown' | |
312 | end | |
293 | 313 | return markdown_processor(ldoc, formatter) |
294 | 314 | end |
295 | 315 | |
349 | 369 | return processor |
350 | 370 | end |
351 | 371 | |
352 | ||
353 | 372 | return markup |
19 | 19 | |
20 | 20 | -- a pattern particular to LuaDoc tag lines: the line must begin with @TAG, |
21 | 21 | -- followed by the value, which may extend over several lines. |
22 | local luadoc_tag = '^%s*@(%a+)' | |
22 | local luadoc_tag = '^%s*@(%w+)' | |
23 | 23 | local luadoc_tag_value = luadoc_tag..'(.*)' |
24 | 24 | local luadoc_tag_mod_and_value = luadoc_tag..'%[(.*)%](.*)' |
25 | 25 | |
353 | 353 | |
354 | 354 | -- end of a block of document comments |
355 | 355 | if ldoc_comment and tags then |
356 | local line = t ~= nil and lineno() | |
356 | local line = lineno() | |
357 | 357 | if t ~= nil then |
358 | 358 | if item_follows then -- parse the item definition |
359 | 359 | local err = item_follows(tags,tok) |
23 | 23 | |
24 | 24 | local spans = {keyword=true,number=true,string=true,comment=true,global=true,backtick=true} |
25 | 25 | |
26 | local cpp_lang = {c = true, cpp = true, cxx = true, h = true} | |
26 | local cpp_lang = {C = true, c = true, cpp = true, cxx = true, h = true} | |
27 | 27 | |
28 | function prettify.lua (lang, fname, code, initial_lineno, pre) | |
28 | function prettify.lua (lang, fname, code, initial_lineno, pre, linenos) | |
29 | 29 | local res, lexer, tokenizer = List(), require 'ldoc.lexer' |
30 | 30 | local tnext = lexer.skipws |
31 | local ik = 1 | |
31 | 32 | if not cpp_lang[lang] then |
32 | 33 | tokenizer = lexer.lua |
33 | 34 | else |
49 | 50 | if not t then return nil,"empty file" end |
50 | 51 | while t do |
51 | 52 | val = escape(val) |
53 | if linenos and tok:lineno() == linenos[ik] then | |
54 | res:append('<a id="'..linenos[ik]..'"></a>') | |
55 | ik = ik + 1 | |
56 | end | |
52 | 57 | if globals.functions[val] or globals.tables[val] then |
53 | 58 | t = 'global' |
54 | 59 | end |
108 | 108 | local group = item[self.fieldname] -- which wd be item's type or section |
109 | 109 | local kname = self.klass.types_by_tag[group] -- the kind name |
110 | 110 | if not self[kname] then |
111 | -- print(kname,group,self.fieldname) | |
111 | 112 | self[kname] = M.type_iterator (items,self.fieldname,group) |
112 | 113 | self.klass.descriptions[kname] = description |
113 | 114 | end |
461 | 462 | return res |
462 | 463 | end |
463 | 464 | |
464 | function M.process_file_list (list, mask, operation, ...) | |
465 | function M.getallfiles(root,mask) | |
466 | local res = List(dir.getallfiles(root,mask)) | |
467 | res:sort() | |
468 | return res | |
469 | end | |
470 | ||
471 | function M.expand_file_list (list, mask) | |
465 | 472 | local exclude_list = list.exclude and M.files_from_list(list.exclude, mask) |
466 | 473 | local files = List() |
467 | 474 | local function process (f) |
472 | 479 | end |
473 | 480 | for _,f in ipairs(list) do |
474 | 481 | if path.isdir(f) then |
475 | local dfiles = List(dir.getallfiles(f,mask)) | |
482 | local dfiles = M.getallfiles(f,mask) | |
476 | 483 | for f in dfiles:iter() do |
477 | 484 | process(f) |
478 | 485 | end |
482 | 489 | quit("file or directory does not exist: "..M.quote(f)) |
483 | 490 | end |
484 | 491 | end |
485 | ||
486 | if list.sortfn then | |
487 | files:sort(list.sortfn) | |
488 | end | |
489 | ||
492 | return files | |
493 | end | |
494 | ||
495 | function M.process_file_list (list, mask, operation, ...) | |
496 | local files = M.expand_file_list(list,mask) | |
490 | 497 | for f in files:iter() do |
491 | 498 | operation(f,...) |
492 | 499 | end |
36 | 36 | |
37 | 37 | --- @usage |
38 | 38 | local usage = [[ |
39 | ldoc, a documentation generator for Lua, vs 1.4.2 | |
39 | ldoc, a documentation generator for Lua, vs 1.4.3 | |
40 | 40 | -d,--dir (default doc) output directory |
41 | 41 | -o,--output (default 'index') output name |
42 | 42 | -v,--verbose verbose |
107 | 107 | ['.ldoc'] = lua, |
108 | 108 | ['.luadoc'] = lua, |
109 | 109 | ['.c'] = cc, |
110 | ['.h'] = cc, | |
110 | 111 | ['.cpp'] = cc, |
111 | 112 | ['.cxx'] = cc, |
112 | 113 | ['.C'] = cc, |
148 | 149 | ProjectMap:add_kind(lookup('classmod','Classes')) |
149 | 150 | ProjectMap:add_kind(lookup('topic','Topics')) |
150 | 151 | ProjectMap:add_kind(lookup('example','Examples')) |
152 | ProjectMap:add_kind(lookup('file','Source')) | |
151 | 153 | |
152 | 154 | for k in pairs(kind_names) do |
153 | 155 | if not known_types[k] then |
230 | 232 | 'no_return_or_parms','no_summary','full_description','backtick_references', 'custom_see_handler', |
231 | 233 | 'no_space_before_args','parse_extra','no_lua_ref','sort_modules','use_markdown_titles', |
232 | 234 | 'unqualified', 'custom_display_name_handler', 'kind_names', 'custom_references', |
235 | 'dont_escape_underscore','global_lookup','prettify_files','convert_opt' | |
233 | 236 | } |
234 | 237 | ldoc_contents = tablex.makeset(ldoc_contents) |
235 | 238 | |
419 | 422 | override 'not_luadoc' |
420 | 423 | override 'module_file' |
421 | 424 | override 'boilerplate' |
425 | override 'all' | |
422 | 426 | |
423 | 427 | setup_kinds() |
424 | 428 | |
446 | 450 | end |
447 | 451 | end |
448 | 452 | |
453 | -- process files, optionally in order that respects master module files | |
454 | local function process_all_files(files) | |
455 | local sortfn = reorder_module_file() | |
456 | local files = tools.expand_file_list(files,'*.*') | |
457 | if sortfn then files:sort(sortfn) end | |
458 | for f in files:iter() do | |
459 | process_file(f, file_list) | |
460 | end | |
461 | if #file_list == 0 then quit "no source files found" end | |
462 | end | |
463 | ||
449 | 464 | if type(args.file) == 'table' then |
450 | -- this can only be set from config file so we can assume it's already read | |
451 | args.file.sortfn = reorder_module_file() | |
452 | process_file_list(args.file,'*.*',process_file, file_list) | |
453 | if #file_list == 0 then quit "no source files specified" end | |
465 | -- this can only be set from config file so we can assume config is already read | |
466 | process_all_files(args.file) | |
467 | ||
454 | 468 | elseif path.isdir(args.file) then |
455 | local files = List(dir.getallfiles(args.file,'*.*')) | |
456 | 469 | -- use any configuration file we find, if not already specified |
457 | 470 | if not config_dir then |
471 | local files = List(dir.getallfiles(args.file,'*.*')) | |
458 | 472 | local config_files = files:filter(function(f) |
459 | 473 | return path.basename(f) == args.config |
460 | 474 | end) |
465 | 479 | end |
466 | 480 | end |
467 | 481 | end |
468 | -- process files, optionally in order that respects master module files | |
469 | local sortfn = reorder_module_file() | |
470 | if sortfn then files:sort(sortfn) end | |
471 | for f in files:iter() do | |
472 | process_file(f, file_list) | |
473 | end | |
474 | ||
475 | if #file_list == 0 then | |
476 | quit(quote(args.file).." contained no source files") | |
477 | end | |
482 | ||
483 | process_all_files({args.file}) | |
484 | ||
478 | 485 | elseif path.isfile(args.file) then |
479 | 486 | -- a single file may be accompanied by a config.ld in the same dir |
480 | 487 | if not config_dir then |
520 | 527 | return item, F |
521 | 528 | end |
522 | 529 | |
530 | local function prettify_source_files(files,class,linemap) | |
531 | local prettify = require 'ldoc.prettify' | |
532 | ||
533 | process_file_list (files, '*.*', function(f) | |
534 | local ext = path.extension(f) | |
535 | local ftype = file_types[ext] | |
536 | if ftype then | |
537 | local item = add_special_project_entity(f,{ | |
538 | class = class, | |
539 | }) | |
540 | -- wrap prettify for this example so it knows which file to blame | |
541 | -- if there's a problem | |
542 | local lang = ext:sub(2) | |
543 | item.postprocess = function(code) | |
544 | return '<h2>'..path.basename(f)..'</h2>\n' .. | |
545 | prettify.lua(lang,f,code,0,true,linemap and linemap[f]) | |
546 | end | |
547 | end | |
548 | end) | |
549 | end | |
550 | ||
523 | 551 | if type(ldoc.examples) == 'string' then |
524 | 552 | ldoc.examples = {ldoc.examples} |
525 | 553 | end |
526 | 554 | if type(ldoc.examples) == 'table' then |
527 | local prettify = require 'ldoc.prettify' | |
528 | ||
529 | process_file_list (ldoc.examples, '*.lua', function(f) | |
530 | local item = add_special_project_entity(f,{ | |
531 | class = 'example', | |
532 | }) | |
533 | -- wrap prettify for this example so it knows which file to blame | |
534 | -- if there's a problem | |
535 | local ext = path.extension(f):sub(2) | |
536 | item.postprocess = function(code) return prettify.lua(ext,f,code,0,true) end | |
537 | end) | |
555 | prettify_source_files(ldoc.examples,"example") | |
556 | end | |
557 | ||
558 | if ldoc.prettify_files then | |
559 | local files = List() | |
560 | local linemap = {} | |
561 | for F in file_list:iter() do | |
562 | files:append(F.filename) | |
563 | local mod = F.modules[1] | |
564 | local ls = List() | |
565 | for item in mod.items:iter() do | |
566 | ls:append(item.lineno) | |
567 | end | |
568 | linemap[F.filename] = ls | |
569 | end | |
570 | prettify_source_files(files,"file",linemap) | |
538 | 571 | end |
539 | 572 | |
540 | 573 | if args.simple then |
587 | 620 | project:add(mod,module_list) |
588 | 621 | end |
589 | 622 | |
590 | override 'all' | |
591 | 623 | |
592 | 624 | if ldoc.sort_modules then |
593 | 625 | table.sort(module_list,function(m1,m2) |
720 | 752 | local function tmpwrite (name) |
721 | 753 | local ok,text = pcall(require,'ldoc.html.'..name:gsub('%.','_')) |
722 | 754 | if not ok then |
723 | quit("cannot find builtin template "..name..": "..text) | |
755 | quit("cannot find builtin template "..name) | |
724 | 756 | end |
725 | 757 | if not utils.writefile(path.join(tmpdir,name),text) then |
726 | 758 | quit("cannot write to temp directory "..tmpdir) |
748 | 780 | ldoc.title = ldoc.title or args.title |
749 | 781 | ldoc.project = ldoc.project or args.project |
750 | 782 | ldoc.package = args.package:match '%a+' and args.package or nil |
783 | ldoc.updatetime = os.date("%Y-%m-%d %H:%M:%S") | |
751 | 784 | |
752 | 785 | local html = require 'ldoc.html' |
753 | 786 | |
757 | 790 | print 'modules' |
758 | 791 | for k in pairs(module_list.by_name) do print(k) end |
759 | 792 | end |
760 | ||
761 |
0 | 0 | format='markdown' |
1 | 1 | project = 'Basic Example' |
2 | 2 | file = {'types.lua','classes.lua'} |
3 | topics = {'one.md','two.md'} | |
3 | use_markdown_titles=true | |
4 | topics = {'one 1.md','two.md'} |
15 | 15 | -- @string[opt='gregorian'] calender optional calendar |
16 | 16 | -- @int[opt=0] offset optional offset |
17 | 17 | -- @treturn string |
18 | -- @see file:write | |
18 | 19 | function one (name,age,...) |
19 | 20 | end |
20 | 21 | |
29 | 30 | --- third useless function. |
30 | 31 | -- Can always put comments inline, may |
31 | 32 | -- be multiple. |
32 | -- note that first comment is refers to return | |
33 | -- note that first comment refers to return type! | |
33 | 34 | function three ( -- person: |
34 | 35 | name, -- string: person's name |
35 | 36 | age -- int: |
36 | 37 | -- not less than zero! |
37 | 38 | ) |
39 | end | |
38 | 40 | |
39 | 41 | ---- function with single optional arg |
40 | 42 | -- @param[opt] one |
0 | -- must have explicit optchain! | |
1 | convert_opt = true | |
2 | ||
3 | format = 'markdown' | |
4 | ||
5 | -- want to include project source as well. | |
6 | prettify_files = 'show' | |
7 | ||
8 | -- a custom tag! | |
9 | custom_tags = {{'remark',title='Remarks'}} | |
10 |
0 | ------------ | |
1 | -- Functions with options and custom tags | |
2 | -- | |
3 | -- @include opt.md | |
4 | ||
5 | ---- testing [opt] | |
6 | -- @param one | |
7 | -- @param[opt] two | |
8 | -- @param[opt]three | |
9 | -- @param[opt] four | |
10 | -- @remark use with caution! | |
11 | function use_opt (one,two,three,four) | |
12 | end | |
13 | ||
14 | --- an explicit table. | |
15 | -- Can now use tparam aliases in table defns | |
16 | -- @string name | |
17 | -- @int[opt=0] age | |
18 | -- @table person2 | |
19 |
0 | By default, an unbroken series of opt modifiers is converted to | |
1 | 'opt','optchain','optchain', so you get `(a[,b[,c])`. | |
2 | ||
3 | If `convert_opt` is specified, then no such conversion takes place; you then | |
4 | must explicitly use `optchain`. | |
5 | ||
6 | The `@include` tag is only meaningful for project-level items like modules, | |
7 | scripts, etc. The file is inserted into the document after being formatted. | |
8 | In this case, you would usually specify `format="markdown"`. |