ni_nitdoc: Sorting all list included in a class page
[nit.git] / src / ni_nitdoc.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
3 # Copyright 2008 Jean Privat <jean@pryen.org>
4 #
5 # Licensed under the Apache License, Version 2.0 (the "License");
6 # you may not use this file except in compliance with the License.
7 # You may obtain a copy of the License at
8 #
9 # http://www.apache.org/licenses/LICENSE-2.0
10 #
11 # Unless required by applicable law or agreed to in writing, software
12 # distributed under the License is distributed on an "AS IS" BASIS,
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 # See the License for the specific language governing permissions and
15 # limitations under the License.
16
17 module ni_nitdoc
18
19 import model_utils
20 import abstract_compiler
21 import html
22
23 class Nitdoc
24 private var toolcontext: ToolContext
25 private var model: Model
26 private var modelbuilder: ModelBuilder
27 private var mainmodule: MModule
28 private var arguments: Array[String]
29 private var destinationdir: nullable String
30 private var sharedir: nullable String
31 private var source: nullable String
32
33 private var opt_dir = new OptionString("Directory where doc is generated", "-d", "--dir")
34 private var opt_source = new OptionString("What link for source (%f for filename, %l for first line, %L for last line)", "--source")
35 private var opt_sharedir = new OptionString("Directory containing the nitdoc files", "--sharedir")
36 private var opt_nodot = new OptionBool("Do not generate graphes with graphiviz", "--no-dot")
37
38 init(toolcontext: ToolContext) do
39 # We need a model to collect stufs
40 self.toolcontext = toolcontext
41 self.arguments = toolcontext.option_context.rest
42 toolcontext.option_context.options.clear
43 toolcontext.option_context.add_option(opt_dir)
44 toolcontext.option_context.add_option(opt_source)
45 toolcontext.option_context.add_option(opt_sharedir)
46 toolcontext.option_context.add_option(opt_nodot)
47 toolcontext.process_options
48 process_options
49
50 if arguments.length < 1 then
51 toolcontext.option_context.usage
52 exit(1)
53 end
54
55 model = new Model
56 modelbuilder = new ModelBuilder(model, toolcontext)
57
58 # Here we load an process std modules
59 var mmodules = modelbuilder.parse_and_build([arguments.first])
60 if mmodules.is_empty then return
61 modelbuilder.full_propdef_semantic_analysis
62 assert mmodules.length == 1
63 self.mainmodule = mmodules.first
64 end
65
66 private fun process_options do
67 if not opt_dir.value is null then
68 destinationdir = opt_dir.value
69 else
70 destinationdir = "nitdoc_directory"
71 end
72 if not opt_sharedir.value is null then
73 sharedir = opt_sharedir.value
74 else
75 var dir = "NIT_DIR".environ
76 if dir.is_empty then
77 dir = "{sys.program_name.dirname}/../share/nitdoc"
78 else
79 dir = "{dir}/share/nitdoc"
80 end
81 sharedir = dir
82 if sharedir is null then
83 print "Error: Cannot locate nitdoc share files. Uses --sharedir or envvar NIT_DIR"
84 abort
85 end
86 dir = "{sharedir.to_s}/scripts/js-facilities.js"
87 if sharedir is null then
88 print "Error: Invalid nitdoc share files. Check --sharedir or envvar NIT_DIR"
89 abort
90 end
91 end
92 if not opt_source.value is null then
93 source = ""
94 else
95 source = opt_source.value
96 end
97 end
98
99 fun start do
100 if arguments.length == 1 then
101 # Create destination dir if it's necessary
102 if not destinationdir.file_exists then destinationdir.mkdir
103 sys.system("cp -r {sharedir.to_s}/* {destinationdir.to_s}/")
104 overview
105 fullindex
106 modules
107 classes
108 quicksearch_list
109 end
110 end
111
112 fun overview do
113 var overviewpage = new NitdocOverview.with(modelbuilder.nmodules, self.opt_nodot.value, destinationdir.to_s)
114 overviewpage.save("{destinationdir.to_s}/index.html")
115 end
116
117 fun fullindex do
118 var fullindex = new NitdocFullindex.with(model.mmodules)
119 fullindex.save("{destinationdir.to_s}/full-index.html")
120 end
121
122 fun modules do
123 for mod in modelbuilder.nmodules do
124 var modulepage = new NitdocModules.with(mod)
125 modulepage.save("{destinationdir.to_s}/{mod.mmodule.name}.html")
126 end
127 end
128
129 fun classes do
130 for amodule in modelbuilder.nmodules do
131 for mclass, aclassdef in amodule.mclass2nclassdef do
132 mclass.amodule(modelbuilder.mmodule2nmodule)
133 mclass.mmethod(aclassdef.mprop2npropdef)
134 var classpage = new NitdocMClasses.with(mclass, aclassdef, source)
135 classpage.save("{destinationdir.to_s}/{mclass.name}.html")
136 end
137 end
138 end
139
140 # Generate QuickSearch file
141 fun quicksearch_list do
142 var file = new OFStream.open("{destinationdir.to_s}/quicksearch-list.js")
143 var content = new Buffer
144 content.append("var entries = \{ ")
145 for prop in model.mproperties do
146 if not prop isa MMethod then continue
147 content.append("\"{prop.name}\": [")
148 for propdef in prop.mpropdefs do
149 content.append("\{txt: \"{propdef.mproperty.full_name}\", url:\"{propdef.mproperty.link_anchor}\" \}")
150 if not propdef is prop.mpropdefs.last then content.append(", ")
151 end
152 content.append("]")
153 content.append(", ")
154 end
155
156 for mclass in model.mclasses do
157 content.append("\"{mclass.name}\": [")
158 for mclassdef in mclass.mclassdefs do
159 content.append("\{txt: \"{mclassdef.mclass.full_name}\", url:\"{mclass.link_anchor}\" \}")
160 if not mclassdef is mclass.mclassdefs.last then content.append(", ")
161 end
162 content.append("]")
163 if not mclass is model.mclasses.last then content.append(", ")
164 end
165
166 content.append(" \};")
167 file.write(content.to_s)
168 file.close
169 end
170
171 end
172
173 class NitdocOverview
174 super NitdocPage
175
176 var amodules: Array[AModule]
177
178 # Init with Array[AModule] to get all ifnormations about each MModule containt in a program
179 # opt_nodot to inform about the graph gen
180 # destination: to know where will be saved dot files
181 init with(modules: Array[AModule], opt_nodot: Bool, destination: String) do
182 self.amodules = modules
183 self.opt_nodot = opt_nodot
184 self.destinationdir = destination
185 end
186
187 redef fun head do
188 super
189 add("title").text("Overview | Nit Standard Library")
190 end
191
192 redef fun header do
193 open("header")
194 open("nav").add_class("main")
195 open("ul")
196 add("li").add_class("current").text("Overview")
197 open("li")
198 add_html("<a href=\"full-index.html\">Full Index</a>")
199 close("li")
200 open("li").attr("id", "liGitHub")
201 open("a").add_class("btn").attr("id", "logGitHub")
202 add("img").attr("id", "imgGitHub").attr("src", "resources/icons/github-icon.png")
203 close("a")
204 open("div").add_class("popover bottom")
205 add("div").add_class("arrow").text(" ")
206 open("div").add_class("githubTitle")
207 add("h3").text("Github Sign In")
208 close("div")
209 open("div")
210 add("label").attr("id", "lbloginGit").text("Username")
211 add("input").attr("id", "loginGit").attr("name", "login").attr("type", "text")
212 open("label").attr("id", "logginMessage").text("Hello ")
213 open("a").attr("id", "githubAccount")
214 add("strong").attr("id", "nickName").text(" ")
215 close("a")
216 close("label")
217 close("div")
218 open("div")
219 add("label").attr("id", "lbpasswordGit").text("Password")
220 add("input").attr("id", "passwordGit").attr("name", "password").attr("type", "password")
221 open("div").attr("id", "listBranches")
222 add("label").attr("id", "lbBranches").text("Branch")
223 add("select").add_class("dropdown").attr("id", "dropBranches").attr("name", "dropBranches").attr("tabindex", "1").text(" ")
224 close("div")
225 close("div")
226 open("div")
227 add("label").attr("id", "lbrepositoryGit").text("Repository")
228 add("input").attr("id", "repositoryGit").attr("name", "repository").attr("type", "text")
229 close("div")
230 open("div")
231 add("label").attr("id", "lbbranchGit").text("Branch")
232 add("input").attr("id", "branchGit").attr("name", "branch").attr("type", "text")
233 close("div")
234 open("div")
235 add("a").attr("id", "signIn").text("Sign In")
236 close("div")
237 close("div")
238 close("li")
239 close("ul")
240 close("nav")
241 close("header")
242 end
243
244 redef fun body do
245 super
246 open("div").add_class("page")
247 open("div").add_class("content fullpage")
248 add("h1").text("Nit Standard Library")
249 open("article").add_class("overview")
250 add_html("<p>Documentation for the standard library of Nit<br />Version jenkins-component=stdlib-19<br />Date: TODAY</p>")
251 close("article")
252 open("article").add_class("overview")
253 add("h2").text("Modules")
254 open("ul")
255 add_modules
256 close("ul")
257 process_generate_dot
258 close("article")
259 close("div")
260 close("div")
261 add("footer").text("Nit standard library. Version jenkins-component=stdlib-19.")
262 end
263
264 fun add_modules do
265 var ls = new List[nullable MModule]
266 for amodule in amodules do
267 var mmodule = amodule.mmodule.public_owner
268 if mmodule != null and not ls.has(mmodule) then
269 open("li")
270 add("a").attr("href", "{mmodule.name}.html").text("{mmodule.to_s} ")
271 add_html(amodule.comment)
272 close("li")
273 ls.add(mmodule)
274 end
275 end
276 end
277
278 fun process_generate_dot do
279 var op = new Buffer
280 op.append("digraph dep \{ rankdir=BT; node[shape=none,margin=0,width=0,height=0,fontsize=10]; edge[dir=none,color=gray]; ranksep=0.2; nodesep=0.1;\n")
281 for amodule in amodules do
282 op.append("\"{amodule.mmodule.name}\"[URL=\"{amodule.mmodule.name}.html\"];\n")
283 for mmodule2 in amodule.mmodule.in_importation.direct_greaters do
284 op.append("\"{amodule.mmodule.name}\"->\"{mmodule2.name}\";\n")
285 end
286 end
287 op.append("\}\n")
288 generate_dot(op.to_s, "dep", "Modules hierarchy")
289 end
290
291 end
292
293 class NitdocFullindex
294 super NitdocPage
295
296 var mmodules: Array[MModule]
297
298 init with(mmodules: Array[MModule]) do
299 self.mmodules = mmodules
300 opt_nodot = false
301 destinationdir = ""
302 end
303
304 redef fun head do
305 super
306 add("title").text("Full Index | Nit Standard Library")
307 end
308
309 redef fun header do
310 open("header")
311 open("nav").add_class("main")
312 open("ul")
313 open("li")
314 add_html("<a href=\"index.html\">Overview</a>")
315 close("li")
316 add("li").add_class("current").text("Full Index")
317 open("li").attr("id", "liGitHub")
318 open("a").add_class("btn").attr("id", "logGitHub")
319 add("img").attr("id", "imgGitHub").attr("src", "resources/icons/github-icon.png")
320 close("a")
321 open("div").add_class("popover bottom")
322 add("div").add_class("arrow").text(" ")
323 open("div").add_class("githubTitle")
324 add("h3").text("Github Sign In")
325 close("div")
326 open("div")
327 add("label").attr("id", "lbloginGit").text("Username")
328 add("input").attr("id", "loginGit").attr("name", "login").attr("type", "text")
329 open("label").attr("id", "logginMessage").text("Hello ")
330 open("a").attr("id", "githubAccount")
331 add("strong").attr("id", "nickName").text(" ")
332 close("a")
333 close("label")
334 close("div")
335 open("div")
336 add("label").attr("id", "lbpasswordGit").text("Password")
337 add("input").attr("id", "passwordGit").attr("name", "password").attr("type", "password")
338 open("div").attr("id", "listBranches")
339 add("label").attr("id", "lbBranches").text("Branch")
340 add("select").add_class("dropdown").attr("id", "dropBranches").attr("name", "dropBranches").attr("tabindex", "1").text(" ")
341 close("div")
342 close("div")
343 open("div")
344 add("label").attr("id", "lbrepositoryGit").text("Repository")
345 add("input").attr("id", "repositoryGit").attr("name", "repository").attr("type", "text")
346 close("div")
347 open("div")
348 add("label").attr("id", "lbbranchGit").text("Branch")
349 add("input").attr("id", "branchGit").attr("name", "branch").attr("type", "text")
350 close("div")
351 open("div")
352 add("a").attr("id", "signIn").text("Sign In")
353 close("div")
354 close("div")
355 close("li")
356 close("ul")
357 close("nav")
358 close("header")
359 end
360
361 redef fun body do
362 super
363 open("div").add_class("page")
364 open("div").add_class("content fullpage")
365 add("h1").text("Full Index")
366 add_content
367 close("div")
368 close("div")
369 add("footer").text("Nit standard library. Version jenkins-component=stdlib-19.")
370 end
371
372 fun add_content do
373 module_column
374 classes_column
375 properties_column
376 end
377
378 # Add to content modules column
379 fun module_column do
380 var ls = new List[nullable MModule]
381 var sorted = mmodules
382 var sorterp = new ComparableSorter[MModule]
383 sorterp.sort(sorted)
384 open("article").add_class("modules filterable")
385 add("h2").text("Modules")
386 open("ul")
387 for mmodule in sorted do
388 if mmodule.public_owner != null and not ls.has(mmodule.public_owner) then
389 ls.add(mmodule.public_owner)
390 open("li")
391 add("a").attr("href", "{mmodule.public_owner.name}.html").text(mmodule.public_owner.name)
392 close("li")
393 end
394 end
395 close("ul")
396 close("article")
397 end
398
399 # Add to content classes modules
400 fun classes_column do
401 var sorted = mmodules.first.imported_mclasses.to_a
402 var sorterp = new ComparableSorter[MClass]
403 sorterp.sort(sorted)
404 open("article").add_class("classes filterable")
405 add("h2").text("Classes")
406 open("ul")
407
408 for mclass in sorted do
409 open("li")
410 add("a").attr("href", "{mclass.name}.html").text(mclass.name)
411 close("li")
412 end
413
414 close("ul")
415 close("article")
416 end
417
418 # Insert the properties column of fullindex page
419 fun properties_column do
420 open("article").add_class("properties filterable")
421 add("h2").text("Properties")
422 open("ul")
423 var sorted_imported = mmodules.first.imported_methods.to_a
424 var sorted_redef = mmodules.first.redef_methods.to_a
425 var sorterp = new ComparableSorter[MProperty]
426 sorterp.sort(sorted_imported)
427 sorterp.sort(sorted_redef)
428
429 for method in sorted_imported do
430 if method.visibility is none_visibility or method.visibility is intrude_visibility then continue
431 open("li").add_class("intro")
432 add("span").attr("title", "introduction").text("I")
433 add_html("&nbsp;")
434 add("a").attr("href", "{method.local_class.name}.html").attr("title", "").text("{method.name} ({method.local_class.name})")
435 close("li")
436 end
437
438 for method in sorted_redef do
439 if method.visibility is none_visibility or method.visibility is intrude_visibility then continue
440 open("li").add_class("redef")
441 add("span").attr("title", "redefinition").text("R")
442 add_html("&nbsp;")
443 add("a").attr("href", "{method.local_class.name}.html").attr("title", "").text("{method.name} ({method.local_class.name})")
444 close("li")
445 end
446
447 close("ul")
448 close("article")
449 end
450
451 end
452
453 class NitdocModules
454 super NitdocPage
455
456 var amodule: AModule
457 var modulename: String
458 init with(amodule: AModule) do
459 self.amodule = amodule
460 self.modulename = self.amodule.mmodule.name
461 opt_nodot = false
462 destinationdir = ""
463 end
464
465 redef fun head do
466 super
467 add("title").text("{modulename} module | {amodule.short_comment}")
468 end
469
470 redef fun header do
471 open("header")
472 open("nav").add_class("main")
473 open("ul")
474 open("li")
475 add_html("<a href=\"index.html\">Overview</a>")
476 close("li")
477 add("li").add_class("current").text(modulename)
478 open("li")
479 add_html("<a href=\"full-index.html\" >Full Index</a>")
480 close("li")
481 open("li").attr("id", "liGitHub")
482 open("a").add_class("btn").attr("id", "logGitHub")
483 add("img").attr("id", "imgGitHub").attr("src", "resources/icons/github-icon.png")
484 close("a")
485 open("div").add_class("popover bottom")
486 add("div").add_class("arrow").text(" ")
487 open("div").add_class("githubTitle")
488 add("h3").text("Github Sign In")
489 close("div")
490 open("div")
491 add("label").attr("id", "lbloginGit").text("Username")
492 add("input").attr("id", "loginGit").attr("name", "login").attr("type", "text")
493 open("label").attr("id", "logginMessage").text("Hello ")
494 open("a").attr("id", "githubAccount")
495 add("strong").attr("id", "nickName").text(" ")
496 close("a")
497 close("label")
498 close("div")
499 open("div")
500 add("label").attr("id", "lbpasswordGit").text("Password")
501 add("input").attr("id", "passwordGit").attr("name", "password").attr("type", "password")
502 open("div").attr("id", "listBranches")
503 add("label").attr("id", "lbBranches").text("Branch")
504 add("select").add_class("dropdown").attr("id", "dropBranches").attr("name", "dropBranches").attr("tabindex", "1").text(" ")
505 close("div")
506 close("div")
507 open("div")
508 add("label").attr("id", "lbrepositoryGit").text("Repository")
509 add("input").attr("id", "repositoryGit").attr("name", "repository").attr("type", "text")
510 close("div")
511 open("div")
512 add("label").attr("id", "lbbranchGit").text("Branch")
513 add("input").attr("id", "branchGit").attr("name", "branch").attr("type", "text")
514 close("div")
515 open("div")
516 add("a").attr("id", "signIn").text("Sign In")
517 close("div")
518 close("div")
519 close("li")
520 close("ul")
521 close("nav")
522 close("header")
523 end
524
525 redef fun body do
526 super
527 open("div").add_class("page")
528 menu
529 add_content
530 close("div")
531 add("footer").text("Nit standard library. Version jenkins-component=stdlib-19.")
532 end
533
534 # Insert all tags in content part
535 fun add_content do
536 open("div").add_class("content")
537 add("h1").text(modulename)
538 add("div").add_class("subtitle").text("module {modulename}")
539 module_comment
540 classes
541 properties
542 close("div")
543 end
544
545 # Insert module comment in the content
546 fun module_comment do
547 var doc = amodule.comment
548 open("div").attr("id", "description")
549 add("pre").add_class("text_label").text(doc)
550 add("textarea").add_class("edit").attr("rows", "1").attr("cols", "76").attr("id", "fileContent").text(" ")
551 add("a").attr("id", "cancelBtn").text("Cancel")
552 add("a").attr("id", "commitBtn").text("Commit")
553 add("pre").add_class("text_label").attr("id", "preSave").attr("type", "2")
554 close("div")
555 end
556
557 fun menu do
558 var mmodule = amodule.mmodule
559 open("div").add_class("menu")
560 open("nav")
561 add("h3").text("Module Hierarchy").attr("style","cursor: pointer;")
562 if mmodule.in_importation.direct_greaters.length > 0 then
563 add_html("<h4>All dependencies</h4><ul>")
564 var sorted = mmodule.in_importation.direct_greaters.to_a
565 var sorterp = new ComparableSorter[MModule]
566 sorterp.sort(sorted)
567 for m in sorted do
568 if m == mmodule or mmodule == m.public_owner then continue
569 open("li")
570 add("a").attr("href", "{m.name}.html").text(m.name)
571 close("li")
572 end
573 add_html("</ul>")
574 end
575 if mmodule.in_importation.greaters.length > 0 then
576 add_html("<h4>All clients</h4><ul>")
577 var sorted = mmodule.in_importation.greaters.to_a
578 var sorterp = new ComparableSorter[MModule]
579 sorterp.sort(sorted)
580 for m in sorted do
581 if m == mmodule then continue
582 open("li")
583 add("a").attr("href", "{m.name}.html").text(m.name)
584 close("li")
585 end
586 add_html("</ul>")
587 end
588 close("nav")
589 if mmodule.in_nesting.direct_greaters.length > 0 then
590 var sorted = mmodule.in_nesting.direct_greaters.to_a
591 var sorterp = new ComparableSorter[MModule]
592 sorterp.sort(sorted)
593 open("nav")
594 add("h3").text("Nested Modules").attr("style","cursor: pointer;")
595 open("ul")
596 for m in sorted do
597 open("li")
598 add("a").attr("href", "{m.name}.html").text(m.name)
599 close("li")
600 end
601 close("ul")
602
603 close("nav")
604 end
605 close("div")
606 end
607
608 fun classes do
609 var sorted = new Array[MClass]
610 sorted.add_all(amodule.mmodule.mclasses.keys)
611 var sorterp = new ComparableSorter[MClass]
612 sorterp.sort(sorted)
613 open("div").add_class("module")
614 open("article").add_class("classes filterable")
615 add("h2").text("Classes")
616 open("ul")
617 for c in sorted do
618 var state = amodule.mmodule.mclasses[c]
619 var name = c.name
620 if state == c_is_intro or state == c_is_imported then
621 open("li").add_class("intro")
622 add("span").attr("title", "introduced in this module").text("I ")
623 else
624 open("li").add_class("redef")
625 add("span").attr("title", "refined in this module").text("R ")
626 end
627 add("a").attr("href", "{name}.html").text(name)
628 close("li")
629 end
630 close("ul")
631 close("article")
632 close("div")
633 end
634
635 fun properties do
636 var sorted_imported = amodule.mmodule.imported_methods.to_a
637 var sorted_redef = amodule.mmodule.redef_methods.to_a
638 var sorterp = new ComparableSorter[MProperty]
639 sorterp.sort(sorted_imported)
640 sorterp.sort(sorted_redef)
641 open("article").add_class("properties filterable")
642 add_html("<h2>Properties</h2>")
643 open("ul")
644 for method in sorted_imported do
645 if method.visibility is none_visibility or method.visibility is intrude_visibility then continue
646 open("li").add_class("intro")
647 add("span").attr("title", "introduction").text("I")
648 add_html("&nbsp;")
649 add("a").attr("href", "{method.local_class.name}.html").attr("title", "").text("{method.name} ({method.local_class.name})")
650 close("li")
651 end
652
653 for method in sorted_redef do
654 if method.visibility is none_visibility or method.visibility is intrude_visibility then continue
655 open("li").add_class("redef")
656 add("span").attr("title", "redefinition").text("R")
657 add_html("&nbsp;")
658 add("a").attr("href", "{method.local_class.name}.html").attr("title", "").text("{method.name} ({method.local_class.name})")
659 close("li")
660 end
661
662 close("ul")
663 close("article")
664 end
665
666 end
667
668 # Nit Standard Library
669 class NitdocMClasses
670 super NitdocPage
671
672 var mclass: MClass
673 var aclassdef: AClassdef
674 var stdclassdef: nullable AStdClassdef
675 var public_owner: nullable MModule
676
677 init with(mclass: MClass, aclassdef: AClassdef, source: nullable String) do
678 self.mclass = mclass
679 self.aclassdef = aclassdef
680 if aclassdef isa AStdClassdef then self.stdclassdef = aclassdef
681 self.public_owner = mclass.intro_mmodule.public_owner
682 opt_nodot = false
683 destinationdir = ""
684 self.source = source
685 end
686
687 redef fun head do
688 super
689 add("title").text("{self.mclass.name} class | Nit Standard Library")
690 end
691
692 redef fun header do
693 open("header")
694 open("nav").add_class("main")
695 open("ul")
696 open("li")
697 add_html("<a href=\"index.html\">Overview</a>")
698 close("li")
699 open("li")
700 if public_owner is null then
701 add_html("<a href=\"{mclass.intro_mmodule.name}.html\">{mclass.intro_mmodule.name}</a>")
702 else
703 add_html("<a href=\"{public_owner.name}.html\">{public_owner.name}</a>")
704 end
705 close("li")
706 add("li").add_class("current").text(mclass.name)
707 open("li")
708 add_html("<a href=\"full-index.html\" >Full Index</a>")
709 close("li")
710 open("li").attr("id", "liGitHub")
711 open("a").add_class("btn").attr("id", "logGitHub")
712 add("img").attr("id", "imgGitHub").attr("src", "resources/icons/github-icon.png")
713 close("a")
714 open("div").add_class("popover bottom")
715 add("div").add_class("arrow").text(" ")
716 open("div").add_class("githubTitle")
717 add("h3").text("Github Sign In")
718 close("div")
719 open("div")
720 add("label").attr("id", "lbloginGit").text("Username")
721 add("input").attr("id", "loginGit").attr("name", "login").attr("type", "text")
722 open("label").attr("id", "logginMessage").text("Hello ")
723 open("a").attr("id", "githubAccount")
724 add("strong").attr("id", "nickName").text(" ")
725 close("a")
726 close("label")
727 close("div")
728 open("div")
729 add("label").attr("id", "lbpasswordGit").text("Password")
730 add("input").attr("id", "passwordGit").attr("name", "password").attr("type", "password")
731 open("div").attr("id", "listBranches")
732 add("label").attr("id", "lbBranches").text("Branch")
733 add("select").add_class("dropdown").attr("id", "dropBranches").attr("name", "dropBranches").attr("tabindex", "1").text(" ")
734 close("div")
735 close("div")
736 open("div")
737 add("label").attr("id", "lbrepositoryGit").text("Repository")
738 add("input").attr("id", "repositoryGit").attr("name", "repository").attr("type", "text")
739 close("div")
740 open("div")
741 add("label").attr("id", "lbbranchGit").text("Branch")
742 add("input").attr("id", "branchGit").attr("name", "branch").attr("type", "text")
743 close("div")
744 open("div")
745 add("a").attr("id", "signIn").text("Sign In")
746 close("div")
747 close("div")
748 close("li")
749 close("ul")
750 close("nav")
751 close("header")
752 end
753
754 redef fun body do
755 super
756 open("div").add_class("page")
757 add_content
758 close("div")
759 add("footer").text("Nit standard library. Version jenkins-component=stdlib-19.")
760 end
761
762 # Insert all tags in content part
763 fun add_content do
764 open("div").add_class("menu")
765 properties_column
766 inheritance_column
767 close("div")
768 open("div").add_class("content")
769 content
770 close("div")
771 end
772
773 fun properties_column do
774 var sorted = new Array[MProperty]
775 var sorterp = new ComparableSorter[MProperty]
776 open("nav").add_class("properties filterable")
777 add("h3").text("Properties")
778
779 if mclass.virtual_types.length > 0 then
780 add("h4").text("Virtual Types")
781 open("ul")
782 sorted = mclass.virtual_types.to_a
783 sorterp.sort(sorted)
784 for prop in sorted do
785 add_html("<li class=\"redef\"><span title=\"Redefined\">R</span><a href=\"{prop.link_anchor}\">{prop.name}</a></li>")
786 end
787 close("ul")
788 end
789 if mclass.constructors.length > 0 then
790 sorted = mclass.constructors.to_a
791 sorterp.sort(sorted)
792 add("h4").text("Constructors")
793 open("ul")
794 for prop in sorted do
795 add_html("<li class=\"intro\"><span title=\"Introduced\">I</span><a href=\"{prop.link_anchor}\">{prop.name}</a></li>")
796 end
797 close("ul")
798 end
799 add("h4").text("Methods")
800 open("ul")
801 if mclass.intro_methods.length > 0 then
802 sorted = mclass.intro_methods.to_a
803 sorterp.sort(sorted)
804 for prop in sorted do
805 if prop.visibility is public_visibility or prop.visibility is protected_visibility then add_html("<li class=\"intro\"><span title=\"Introduced\">I</span><a href=\"{prop.link_anchor}\">{prop.name}</a></li>")
806 end
807 end
808 if mclass.inherited_methods.length > 0 then
809 sorted = mclass.inherited_methods.to_a
810 sorterp.sort(sorted)
811 for prop in sorted do
812 if prop.visibility is public_visibility or prop.visibility is protected_visibility then add_html("<li class=\"inherit\"><span title=\"Inherited\">H</span><a href=\"{prop.link_anchor}\">{prop.name}</a></li>")
813 end
814 end
815 if mclass.redef_methods.length > 0 then
816 sorted = mclass.redef_methods.to_a
817 sorterp.sort(sorted)
818 for prop in sorted do
819 if prop.visibility is public_visibility or prop.visibility is protected_visibility then add_html("<li class=\"redef\"><span title=\"Refined\">R</span><a href=\"{prop.link_anchor}\">{prop.name}</a></li>")
820 end
821 end
822 close("ul")
823 close("nav")
824 end
825
826 fun inheritance_column do
827 var sorted = new Array[MClass]
828 var sorterp = new ComparableSorter[MClass]
829 open("nav")
830 add("h3").text("Inheritance")
831 if mclass.parents.length > 0 then
832 sorted = mclass.parents.to_a
833 sorterp.sort(sorted)
834 add("h4").text("Superclasses")
835 open("ul")
836 for sup in sorted do add_html("<li><a href=\"{sup.name}.html\">{sup.name}</a></li>")
837 close("ul")
838 end
839
840 if mclass.descendants.length is 0 then
841 add("h4").text("No Known Subclasses")
842 else if mclass.descendants.length <= 100 then
843 sorted = mclass.descendants.to_a
844 sorterp.sort(sorted)
845 add("h4").text("Subclasses")
846 open("ul")
847 for sub in sorted do add_html("<li><a href=\"{sub.name}\">{sub.name}</a></li>")
848 close("ul")
849 else if mclass.children.length <= 100 then
850 sorted = mclass.children.to_a
851 sorterp.sort(sorted)
852 add("h4").text("Direct Subclasses Only")
853 open("ul")
854 for sub in sorted do add_html("<li><a href=\"{sub.name}\">{sub.name}</a></li>")
855 close("ul")
856 else
857 add("h4").text("Too much Subclasses to list")
858 end
859 close("nav")
860 end
861
862 fun content do
863 var sorted = new Array[MModule]
864 sorted.add_all(mclass.concerns.keys)
865 var sorterp = new ComparableSorter[MModule]
866 var sorterprop = new ComparableSorter[MProperty]
867 var sorterc = new ComparableSorter[MClass]
868 sorterp.sort(sorted)
869 var subtitle = ""
870 var lmmodule = new List[MModule]
871 # Insert the subtitle part
872 add("h1").text(mclass.name)
873 open("div").add_class("subtitle")
874 if mclass.visibility is none_visibility then subtitle += "private "
875 subtitle += "{mclass.kind} <a href=\"{mclass.public_owner.name}.html\">{mclass.public_owner.name}</a>::{mclass.name}"
876 add_html(subtitle)
877 close("div")
878 add_html("<div style=\"float: right;\"><a id=\"lblDiffCommit\"></a></div>")
879 # We add the class description
880 open("section").add_class("description")
881 if not stdclassdef is null and not stdclassdef.comment.is_empty then add_html("<pre class=\"text_label\" title=\"122\" name=\"\" tag=\"{mclass.mclassdefs.first.location.to_s}\" type=\"2\">{stdclassdef.comment} </pre><textarea id=\"fileContent\" class=\"edit\" cols=\"76\" rows=\"1\" style=\"display: none;\"></textarea><a id=\"cancelBtn\" style=\"display: none;\">Cancel</a><a id=\"commitBtn\" style=\"display: none;\">Commit</a><pre id=\"preSave\" class=\"text_label\" type=\"2\"></pre>")
882 close("section")
883 open("section").add_class("concerns")
884 add("h2").add_class("section-header").text("Concerns")
885 open("ul")
886 for owner in sorted do
887 var childs = mclass.concerns[owner]
888 open("li")
889 add_html("<a href=\"#MOD_{owner.name}\">{owner.name}</a>: {owner.amodule.short_comment}")
890 if not childs is null then
891 open("ul")
892 var sortedc = childs.to_a
893 var sorterpc = new ComparableSorter[MModule]
894 sorterpc.sort(sortedc)
895 for child in sortedc do
896 add_html("<li><a href=\"#MOD_{child.name}\">{child.name}</a>: {child.amodule.short_comment} </li>")
897 end
898 close("ul")
899 end
900 close("li")
901 end
902 close("ul")
903 close("section")
904 # Insert virtual types if there is almost one
905 if mclass.virtual_types.length > 0 or (stdclassdef != null and stdclassdef.n_formaldefs.length > 0) then
906 open("section").add_class("types")
907 add("h2").text("Formal and Virtual Types")
908 if mclass.virtual_types.length > 0 then for prop in mclass.virtual_types do description(prop)
909 if stdclassdef.n_formaldefs.length > 0 then
910 for prop in stdclassdef.n_formaldefs do
911 open("article").attr("id", "FT_Object_{prop.collect_text}")
912 open("h3").add_class("signature").text("{prop.collect_text}: nullable ")
913 add_html("<a title=\"The root of the class hierarchy.\" href=\"Object.html\">Object</a>")
914 close("h3")
915 add_html("<div class=\"info\">formal generic type</div>")
916 close("article")
917 end
918 end
919 close("section")
920 end
921 # Insert constructors if there is almost one
922 if mclass.constructors.length > 0 then
923 var sortedc = mclass.constructors.to_a
924 sorterprop.sort(sortedc)
925 open("section").add_class("constructors")
926 add("h2").add_class("section-header").text("Constructors")
927 for prop in sortedc do description(prop)
928 close("section")
929 end
930 open("section").add_class("methods")
931 add("h2").add_class("section-header").text("Methods")
932 for mmodule, mmethods in mclass.all_methods do
933 add_html("<a id=\"MOD_{mmodule.name}\"></a>")
934 if mmodule != mclass.intro_mmodule and mmodule != mclass.public_owner then
935 if mclass.has_mmodule(mmodule) then
936 add_html("<p class=\"concern-doc\">{mmodule.name}: {mmodule.amodule.short_comment}</p>")
937 else
938 add_html("<h3 class=\"concern-toplevel\">Methods refined in <a href=\"{mmodule.name}.html\">{mmodule.name}</a></h3><p class=\"concern-doc\">{mmodule.name}: {mmodule.amodule.short_comment}</p>")
939 end
940 end
941 var sortedc = mmethods.to_a
942 sorterprop.sort(sortedc)
943 for prop in sortedc do description(prop)
944 end
945 # Insert inherited methods
946 if mclass.inherited_methods.length > 0 then
947 var sortedc = new Array[MClass]
948 sortedc.add_all(mclass.inherited.keys)
949 sorterc.sort(sortedc)
950 add("h3").text("Inherited Methods")
951 for i_mclass in sortedc do
952 var sortedp = mclass.inherited[i_mclass].to_a
953 sorterprop.sort(sortedp)
954 open("p")
955 add_html("Defined in <a href=\"{i_mclass.name}.html\">{i_mclass.name}</a>: ")
956 for method in sortedp do
957 add_html("<a href=\"{method.link_anchor}\">{method.name}</a>")
958 if method != sortedp.last then add_html(", ")
959 end
960 close("p")
961 end
962 end
963 close("section")
964 end
965
966 # Insert description tags for 'prop'
967 fun description(prop: MProperty) do
968 open("article").add_class("fun public {if prop.is_redef then "redef" else ""}").attr("id", "{prop.anchor}")
969 var sign = prop.name
970 if prop.apropdef != null then sign += prop.apropdef.signature
971 add_html("<h3 class=\"signature\">{sign}</h3>")
972 add_html("<div class=\"info\">{if prop.is_redef then "redef" else ""} fun {prop.intro_mclassdef.namespace(mclass)}::{prop.name}</div><div style=\"float: right;\"><a id=\"lblDiffCommit\"></a></div>")
973
974 open("div").add_class("description")
975 if prop.apropdef is null or prop.apropdef.comment == "" then
976 add_html("<a class=\"newComment\" title=\"32\" tag=\"\">New Comment</a>")
977 else
978 add_html("<pre class=\"text_label\" title=\"\" name=\"\" tag=\"\" type=\"1\">{prop.apropdef.comment}</pre>")
979 end
980 add_html("<textarea id=\"fileContent\" class=\"edit\" cols=\"76\" rows=\"1\" style=\"display: none;\"></textarea><a id=\"cancelBtn\" style=\"display: none;\">Cancel</a><a id=\"commitBtn\" style=\"display: none;\">Commit</a><pre id=\"preSave\" class=\"text_label\" type=\"2\"></pre>")
981 open("p")
982 if prop.local_class != mclass then add_html("inherited from {prop.local_class.intro_mmodule.name} ")
983 #TODO display show code if doc github
984 add_html("defined by the module <a href=\"{prop.intro_mclassdef.mmodule.name}.html\">{prop.intro_mclassdef.mmodule.name}</a> {if prop.apropdef is null then "" else show_source(prop.apropdef.location)}.")
985
986 for parent in mclass.parents do
987 if prop isa MMethod then if parent.constructors.has(prop) then add_html(" Previously defined by: <a href=\"{parent.intro_mmodule.name}.html\">{parent.intro_mmodule.name}</a> for <a href=\"{parent.name}.html\">{parent.name}</a>.")
988 end
989 close("p")
990 close("div")
991
992 close("article")
993 end
994
995 end
996
997 class NitdocPage
998 super HTMLPage
999
1000 var opt_nodot: Bool
1001 var destinationdir : String
1002 var source: nullable String
1003
1004 redef fun head do
1005 add("meta").attr("charset", "utf-8")
1006 add("script").attr("type", "text/javascript").attr("src", "scripts/jquery-1.7.1.min.js")
1007 add("script").attr("type", "text/javascript").attr("src", "quicksearch-list.js")
1008 add("script").attr("type", "text/javascript").attr("src", "scripts/js-facilities.js")
1009 add("link").attr("rel", "stylesheet").attr("href", "styles/main.css").attr("type", "text/css").attr("media", "screen")
1010 end
1011
1012 redef fun body do header
1013 fun header do end
1014
1015 # Generate a clickable graphviz image using a dot content
1016 fun generate_dot(dot: String, name: String, alt: String) do
1017 if opt_nodot then return
1018 var file = new OFStream.open("{self.destinationdir}/{name}.dot")
1019 file.write(dot)
1020 file.close
1021 sys.system("\{ test -f {self.destinationdir}/{name}.png && test -f {self.destinationdir}/{name}.s.dot && diff {self.destinationdir}/{name}.dot {self.destinationdir}/{name}.s.dot >/dev/null 2>&1 ; \} || \{ cp {self.destinationdir}/{name}.dot {self.destinationdir}/{name}.s.dot && dot -Tpng -o{self.destinationdir}/{name}.png -Tcmapx -o{self.destinationdir}/{name}.map {self.destinationdir}/{name}.s.dot ; \}")
1022 open("article").add_class("graph")
1023 add("img").attr("src", "{name}.png").attr("usemap", "#{name}").attr("style", "margin:auto").attr("alt", "{alt}")
1024 close("article")
1025 var fmap = new IFStream.open("{self.destinationdir}/{name}.map")
1026 add_html(fmap.read_all)
1027 fmap.close
1028 end
1029
1030 # Add a (source) link fo a given location
1031 fun show_source(l: Location): String
1032 do
1033 if source == null then
1034 return "({l.file.filename.simplify_path})"
1035 else
1036 # THIS IS JUST UGLY ! (but there is no replace yet)
1037 var x = source.split_with("%f")
1038 source = x.join(l.file.filename.simplify_path)
1039 x = source.split_with("%l")
1040 source = x.join(l.line_start.to_s)
1041 x = source.split_with("%L")
1042 source = x.join(l.line_end.to_s)
1043 return " (<a href=\"{source.to_s}\">show code</a>)"
1044 end
1045 end
1046
1047 end
1048
1049 redef class AModule
1050 private fun comment: String do
1051 var ret = ""
1052 if n_moduledecl is null or n_moduledecl.n_doc is null then ret
1053 if n_moduledecl.n_doc is null then return ""
1054 for t in n_moduledecl.n_doc.n_comment do
1055 ret += "{t.text.replace("# ", "")}"
1056 end
1057 return ret
1058 end
1059
1060 private fun short_comment: String do
1061 var ret = ""
1062 if n_moduledecl != null and n_moduledecl.n_doc != null then
1063 var txt = n_moduledecl.n_doc.n_comment.first.text
1064 txt = txt.replace("# ", "")
1065 txt = txt.replace("\n", "")
1066 ret += txt
1067 end
1068 return ret
1069 end
1070 end
1071
1072 redef class MModule
1073
1074 super Comparable
1075 redef type OTHER: MModule
1076 redef fun <(other: OTHER): Bool do return self.name < other.name
1077
1078 var amodule: nullable AModule
1079
1080 # Get the list of all methods in a module
1081 fun imported_methods: Set[MMethod] do
1082 var methods = new HashSet[MMethod]
1083 for mclass in imported_mclasses do
1084 for method in mclass.intro_methods do
1085 methods.add(method)
1086 end
1087 end
1088 return methods
1089 end
1090
1091 # Get the list aof all refined methods in a module
1092 fun redef_methods: Set[MMethod] do
1093 var methods = new HashSet[MMethod]
1094 for mclass in redef_mclasses do
1095 for method in mclass.intro_methods do
1096 methods.add(method)
1097 end
1098 end
1099 return methods
1100 end
1101 end
1102
1103 redef class MProperty
1104
1105 super Comparable
1106 redef type OTHER: MProperty
1107 redef fun <(other: OTHER): Bool do return self.name < other.name
1108
1109 var is_redef: Bool
1110 var apropdef: nullable APropdef
1111
1112 redef init(intro_mclassdef: MClassDef, name: String, visibility: MVisibility)
1113 do
1114 super
1115 is_redef = false
1116 end
1117
1118 fun local_class: MClass do
1119 var classdef = self.intro_mclassdef
1120 return classdef.mclass
1121 end
1122
1123 fun class_text: String do
1124 return local_class.name
1125 end
1126
1127 fun link_anchor: String do
1128 return "{class_text}.html#{anchor}"
1129 end
1130
1131 fun anchor: String do
1132 return "PROP_{c_name}"
1133 end
1134
1135 end
1136
1137 redef class MClass
1138
1139 super Comparable
1140 redef type OTHER: MClass
1141 redef fun <(other: OTHER): Bool do return self.name < other.name
1142
1143 # Associate all MMethods to each MModule concerns
1144 fun all_methods: HashMap[MModule, Set[MMethod]] do
1145 var hm = new HashMap[MModule, Set[MMethod]]
1146 for mmodule, childs in concerns do
1147 if not hm.has_key(mmodule) then hm[mmodule] = new HashSet[MMethod]
1148 for prop in intro_methods do
1149 if mmodule == prop.intro_mclassdef.mmodule then
1150 prop.is_redef = false
1151 hm[mmodule].add(prop)
1152 end
1153 end
1154 for prop in redef_methods do
1155 if mmodule == prop.intro_mclassdef.mmodule then
1156 prop.is_redef = true
1157 hm[mmodule].add(prop)
1158 end
1159 end
1160
1161 if childs != null then
1162 for child in childs do
1163 if not hm.has_key(child) then hm[child] = new HashSet[MMethod]
1164 for prop in intro_methods do
1165 if child == prop.intro_mclassdef.mmodule then
1166 prop.is_redef = false
1167 hm[child].add(prop)
1168 end
1169 end
1170 for prop in redef_methods do
1171 if child == prop.intro_mclassdef.mmodule then
1172 prop.is_redef = true
1173 hm[child].add(prop)
1174 end
1175 end
1176 end
1177 end
1178 end
1179 return hm
1180 end
1181
1182 fun public_owner: MModule do
1183 var owner = intro_mmodule
1184 if owner.public_owner is null then
1185 return owner
1186 else
1187 return owner.public_owner.as(not null)
1188 end
1189 end
1190
1191 # Associate Amodule to all MModule concern by 'self'
1192 fun amodule(amodules: HashMap[MModule, AModule]) do
1193 for owner, childs in concerns do
1194 if childs != null then for child in childs do child.amodule = amodules[child]
1195 owner.amodule = amodules[owner]
1196 end
1197 end
1198
1199 # Associate MClass to all MMethod include in 'inherited_methods'
1200 fun inherited: HashMap[MClass, Set[MMethod]] do
1201 var hm = new HashMap[MClass, Set[MMethod]]
1202 for method in inherited_methods do
1203 var mclass = method.intro_mclassdef.mclass
1204 if not hm.has_key(mclass) then hm[mclass] = new HashSet[MMethod]
1205 hm[mclass].add(method)
1206 end
1207 return hm
1208 end
1209
1210 # Return true if MModule concern contain subMModule
1211 fun has_mmodule(sub: MModule): Bool do
1212 for mmodule, childs in concerns do
1213 if childs is null then continue
1214 if childs.has(sub) then return true
1215 end
1216 return false
1217 end
1218
1219 fun mmethod(mprop2npropdef: Map[MProperty, APropdef]) do
1220 for const in constructors do
1221 if mprop2npropdef.has_key(const)then
1222 const.apropdef = mprop2npropdef[const].as(AMethPropdef)
1223 end
1224 end
1225
1226 for intro in intro_methods do
1227 if mprop2npropdef.has_key(intro)then
1228 if mprop2npropdef[intro] isa AMethPropdef then intro.apropdef = mprop2npropdef[intro].as(AMethPropdef)
1229 end
1230 end
1231
1232 for rd in redef_methods do
1233 if mprop2npropdef.has_key(rd)then
1234 if mprop2npropdef[rd] isa AMethPropdef then rd.apropdef = mprop2npropdef[rd].as(AMethPropdef)
1235 end
1236 end
1237 end
1238
1239 fun link_anchor: String do
1240 return "{name}.html"
1241 end
1242
1243 end
1244
1245 redef class AStdClassdef
1246 private fun comment: String do
1247 var ret = ""
1248 if n_doc != null then
1249 for t in n_doc.n_comment do
1250 var txt = t.text.replace("# ", "")
1251 txt = txt.replace("#", "")
1252 ret += "{txt}"
1253 end
1254 end
1255 return ret
1256 end
1257
1258 private fun short_comment: String do
1259 var ret = ""
1260 if n_doc != null then
1261 var txt = n_doc.n_comment.first.text
1262 txt = txt.replace("# ", "")
1263 txt = txt.replace("\n", "")
1264 ret += txt
1265 end
1266 return ret
1267 end
1268 end
1269
1270 redef class ASignature
1271 redef fun to_s do
1272 #TODO closures
1273 var ret = ""
1274 if not n_params.is_empty then
1275 ret = "{ret}({n_params.join(", ")})"
1276 end
1277 if n_type != null and n_type.to_s != "" then ret += " {n_type.to_s}"
1278 return ret
1279 end
1280 end
1281
1282 redef class AParam
1283 redef fun to_s do
1284 var ret = "{n_id.text}"
1285 if n_type != null then
1286 ret = "{ret}: {n_type.to_s}"
1287 if n_dotdotdot != null then ret = "{ret}..."
1288 end
1289 return ret
1290 end
1291 end
1292
1293 redef class AType
1294 redef fun to_s do
1295 var ret = "<a href=\"{n_id.text}.html\">{n_id.text}</a>"
1296 if n_kwnullable != null then ret = "nullable {ret}"
1297 if not n_types.is_empty then ret = "{ret}[{n_types.join(", ")}]"
1298 return ret
1299 end
1300 end
1301
1302 redef class APropdef
1303 private fun short_comment: String is abstract
1304 private fun signature: String is abstract
1305 private fun comment: String is abstract
1306 end
1307
1308 redef class AAttrPropdef
1309 redef fun short_comment do
1310 var ret = ""
1311 if n_doc != null then
1312 var txt = n_doc.n_comment.first.text
1313 txt = txt.replace("# ", "")
1314 txt = txt.replace("\n", "")
1315 ret += txt
1316 end
1317 return ret
1318 end
1319 end
1320
1321 redef class AMethPropdef
1322 redef fun short_comment do
1323 var ret = ""
1324 if n_doc != null then
1325 var txt = n_doc.n_comment.first.text
1326 txt = txt.replace("# ", "")
1327 txt = txt.replace("\n", "")
1328 ret += txt
1329 end
1330 return ret
1331 end
1332
1333 redef fun signature: String do
1334 var sign = ""
1335 if n_signature != null then sign = " {n_signature.to_s}"
1336 return sign
1337 end
1338
1339 redef private fun comment: String do
1340 var ret = ""
1341 if n_doc != null then
1342 for t in n_doc.n_comment do
1343 var txt = t.text.replace("# ", "")
1344 txt = txt.replace("#", "")
1345 ret += "{txt}"
1346 end
1347 end
1348 return ret
1349 end
1350 end
1351
1352 redef class MClassDef
1353 private fun namespace(mclass: MClass): String do
1354
1355 if mmodule.public_owner is null then
1356 return "{mmodule.full_name}::{mclass.name}"
1357 else if mclass is self.mclass then
1358 return "{mmodule.public_owner.name}::{mclass.name}"
1359 else
1360 return "{mmodule.public_owner.name}::<a href=\"{mclass.name}.html\">{mclass.name}</a>"
1361 end
1362 end
1363 end
1364
1365 redef class Set[E]
1366 fun last: E do
1367 return to_a[length-1]
1368 end
1369 end
1370
1371 # Create a tool context to handle options and paths
1372 var toolcontext = new ToolContext
1373
1374 # Here we launch the nit index
1375 var nitdoc = new Nitdoc(toolcontext)
1376 nitdoc.start