webmcp

view framework/bin/autodoc.lua @ 569:5b19007574de

New argument active_link_attr for env.ui.paginate{...}
author jbe
date Wed Oct 13 17:21:44 2021 +0200 (2021-10-13)
parents ed910089a0c5
children
line source
1 #!/usr/bin/env lua
3 local args = {...}
5 if not args[1] or string.match(args[1], "^%-") then
6 print("Usage: autodoc.lua srcdir/ > documentation.html")
7 os.exit(1)
8 end
10 local entries = {}
12 for idx, srcdir in ipairs(args) do
13 local find_proc = io.popen('find "' .. srcdir .. '" -name \\*.lua', "r")
14 for filename in find_proc:lines() do
15 local synopsis, comment, source
16 local mode
17 local function reset()
18 synopsis, comment, source = {}, {}, {}
19 mode = "idle"
20 end
21 reset()
22 local function strip(tbl)
23 while true do
24 local line = tbl[#tbl]
25 if line and string.find(line, "^%s*$") then
26 tbl[#tbl] = nil
27 else
28 break
29 end
30 end
31 if #tbl > 0 then
32 local min_indent = math.huge
33 for idx, line in ipairs(tbl) do
34 local spaces = string.match(line, "^(%s*)")
35 if min_indent > #spaces then
36 min_indent = #spaces
37 end
38 end
39 local pattern_parts = { "^" }
40 for i = 1, min_indent do
41 pattern_parts[#pattern_parts+1] = "%s"
42 end
43 pattern_parts[#pattern_parts+1] = "(.-)%s*$"
44 local pattern = table.concat(pattern_parts)
45 for idx, line in ipairs(tbl) do
46 tbl[idx] = string.match(line, pattern)
47 end
48 end
49 end
50 local function entry_done()
51 if #synopsis > 0 then
52 strip(synopsis)
53 strip(comment)
54 strip(source)
55 local stripped_synopsis = {}
56 for idx, line in ipairs(synopsis) do
57 local stripped_line = string.match(line, "^(.-)%-%-") or line
58 stripped_line = string.match(stripped_line, "^(.-)%s*$")
59 stripped_synopsis[#stripped_synopsis+1] = stripped_line
60 end
61 local concatted_synopsis = string.gsub(
62 table.concat(stripped_synopsis, " "), "[%s]+", " "
63 )
64 local func_call = string.match(
65 concatted_synopsis, "^[A-Za-z0-9_,. ]+= ?(.-) ?$"
66 )
67 if not func_call then
68 func_call = string.match(
69 concatted_synopsis,
70 "^ ?for[A-Za-z0-9_, ]+in (.-) ? do[ %.]+end ?$"
71 )
72 end
73 if not func_call then
74 func_call = string.match(concatted_synopsis, "^ ?(.-) ?$")
75 end
76 func_call = string.gsub(
77 func_call,
78 "^([^({]*)([({]).*[,;].*[,;].*[,;].*([)}])$",
79 function(base, open, close)
80 return base .. open .. " ... " .. close
81 end
82 )
83 if entries[func_call] then
84 error("Multiple occurrences of: " .. func_call)
85 end
86 entries[func_call] = {
87 func_call = func_call,
88 synopsis = synopsis,
89 comment = comment,
90 source = source
91 }
92 end
93 reset()
94 end
95 for line in io.lines(filename) do
96 local function add_to(tbl)
97 if #tbl > 0 or not string.match(line, "^%s*$") then
98 tbl[#tbl+1] = line
99 end
100 end
101 if mode == "idle" then
102 if string.find(line, "^%s*%-%-%[%[%-%-%s*$") then
103 mode = "synopsis"
104 end
105 elseif mode == "synopsis" then
106 if string.find(line, "^%s*$") and #synopsis > 0 then
107 mode = "comment"
108 elseif string.find(line, "^%s*%-%-]]%-%-%s*$") then
109 mode = "source"
110 else
111 add_to(synopsis)
112 end
113 elseif mode == "comment" then
114 if string.find(line, "^%s*%-%-]]%-%-%s*$") then
115 mode = "source"
116 else
117 add_to(comment)
118 end
119 elseif mode == "source" then
120 if string.find(line, "^%s*%-%-//%-%-%s*$") then
121 entry_done()
122 else
123 add_to(source)
124 end
125 end
126 end
127 entry_done()
128 end
129 find_proc:close()
130 end
133 function output(...)
134 return io.stdout:write(...)
135 end
137 function encode(text)
138 return (
139 string.gsub(
140 text, '[<>&"]',
141 function(char)
142 if char == '<' then
143 return "&lt;"
144 elseif char == '>' then
145 return "&gt;"
146 elseif char == '&' then
147 return "&amp;"
148 elseif char == '"' then
149 return "&quot;"
150 end
151 end
152 )
153 )
154 end
156 function output_lines(tbl)
157 for idx, line in ipairs(tbl) do
158 if idx == 1 then
159 output('<pre>')
160 end
161 local command, comment = string.match(line, "^(.-)(%-%-.*)$")
162 if command then
163 output(
164 encode(command),
165 '<span class="autodoc_comment_tail">', encode(comment), '</span>'
166 )
167 else
168 output(encode(line))
169 end
170 if idx == #tbl then
171 output('</pre>')
172 end
173 output('\n')
174 end
175 end
177 keys = {}
178 for key in pairs(entries) do
179 keys[#keys+1] = key
180 end
181 table.sort(keys)
182 for idx, key in ipairs(keys) do
183 local entry = entries[key]
184 local m1, m2 = string.match(key, "<?([A-Za-z0-9_]*)>?([A-Za-z0-9_.:]+)")
185 local anchor = m1 .. m2
186 output('<li id="', anchor, '" class="autodoc_entry">\n')
187 output(' <div class="short_synopsis" onclick="toggleSection(\'', anchor, '\')">\n')
188 output(' ', encode(entry.func_call), '\n')
189 output(' </div>\n')
190 output(' <div id="autodoc_details_', anchor, '" class="autodoc_details" style="display: none;">\n')
191 output(' <div class="autodoc_synopsis">\n')
192 output_lines(entry.synopsis)
193 output(' </div>\n')
194 output(' <div class="autodoc_comment">')
195 for idx, line in ipairs(entry.comment) do
196 output(encode(line))
197 if idx < #entry.comment then
198 output('<br/>')
199 end
200 end
201 output('</div>\n')
202 output(' <div class="autodoc_source">\n')
203 output_lines(entry.source)
204 output(' </div>\n')
205 output(' </div>\n')
206 output('</li>\n')
207 end

Impressum / About Us