Merge: doc: fixed some typos and other misc. corrections
[nit.git] / src / nitlight.nit
index b22e9f4..4631f4b 100644 (file)
 # Tool that produces highlighting for Nit programs
 module nitlight
 
-import highlight
+import htmlight
+
+class NitlightVisitor
+       super HtmlightVisitor
+
+       # The current highlight module
+       #
+       # It is used to know when to use anchored local links
+       var current_module: MModule
+
+       # List of all highlighted modules
+       #
+       # It is used to have links that only targets highlighted entities
+       #
+       # Entities outside these modules will not be linked.
+       var mmodules: Collection[MModule]
+
+       redef fun hrefto(entity) do return entity.href(self)
+end
+
+redef class MEntity
+       private fun href(v: NitlightVisitor): nullable String do return null
+end
+
+redef class MModule
+       redef fun href(v)
+       do
+               if self == v.current_module then return ""
+               if not v.mmodules.has(self) then return null
+               return c_name + ".html"
+       end
+end
+
+redef class MClass
+       redef fun href(v)
+       do
+               # Because we only have code, just link to the introduction
+               return intro.href(v)
+       end
+end
+
+redef class MClassDef
+       redef fun href(v)
+       do
+               var m = mmodule.href(v)
+               if m == null then return null
+               return m + "#" + to_s
+       end
+end
+
+redef class MProperty
+       redef fun href(v)
+       do
+               # Because we only have code, just link to the introduction
+               return intro.href(v)
+       end
+end
+
+redef class MPropDef
+       redef fun href(v)
+       do
+               var m = mclassdef.mmodule.href(v)
+               if m == null then return null
+               return m + "#" + to_s
+       end
+end
 
 var toolcontext = new ToolContext
 
+# Try to colorize, even if programs are non valid
+toolcontext.keep_going = true
+
 var opt_fragment = new OptionBool("Omit document header and footer", "-f", "--fragment")
+var opt_line_id_prefix = new OptionString("Prefix of the id of each line `<span>` element", "--line-id-prefix")
 var opt_first_line = new OptionInt("Start the source file at this line (default: 1)", 0, "--first-line")
 var opt_last_line = new OptionInt("End the source file at this line (default: to the end)", 0, "--last-line")
 var opt_dir = new OptionString("Output html files in a specific directory (required if more than one module)", "-d", "--dir")
 var opt_full = new OptionBool("Process also imported modules", "--full")
 var opt_ast = new OptionBool("Generate specific HTML elements for each Node of the AST", "--ast")
-toolcontext.option_context.add_option(opt_fragment, opt_first_line, opt_last_line, opt_dir, opt_full)
+var opt_noinfobox = new OptionBool("Disable the generation of infoboxes", "--no-infobox")
+var opt_txt = new OptionBool("Generate text with ANSI coloring escape sequences", "--txt")
+toolcontext.option_context.add_option(opt_fragment, opt_line_id_prefix, opt_first_line, opt_last_line, opt_dir, opt_full, opt_ast, opt_txt, opt_noinfobox)
 toolcontext.tooldescription = "Usage: nitlight [OPTION]... <file.nit>...\nGenerates HTML of highlited code from Nit source files."
 toolcontext.process_options(args)
 
@@ -34,10 +105,10 @@ var modelbuilder = new ModelBuilder(model, toolcontext)
 
 var args = toolcontext.option_context.rest
 
-var mmodules = modelbuilder.parse(args)
+var mmodules = modelbuilder.parse_full(args)
 modelbuilder.run_phases
 
-if opt_full.value then mmodules = model.mmodules
+if opt_full.value then mmodules = modelbuilder.parsed_modules
 
 var dir = opt_dir.value
 if dir != null then
@@ -47,16 +118,47 @@ else if mmodules.length > 1 then
        return
 end
 
+if opt_txt.value then
+       for mm in mmodules do
+               var v = new AnsiHighlightVisitor
+               v.include_loose_tokens = true
+               v.include_whole_lines = true
+
+               if opt_first_line.value != 0 then v.first_line = opt_first_line.value
+               if opt_last_line.value != 0 then v.last_line = opt_last_line.value
+               var m = modelbuilder.mmodule2node(mm)
+               assert m != null
+
+               v.highlight_node(m)
+               var page = v.result
+
+               if dir != null then
+                       page.write_to_file("{dir}/{mm.c_name}.txt")
+               else
+                       page.write_to(stdout)
+               end
+       end
+       return
+end
+
 for mm in mmodules do
-       if dir != null then toolcontext.info("write {dir}/{mm.name}.html", 1)
+       if dir != null then toolcontext.info("write {dir}/{mm.c_name}.html", 1)
 
-       var v = new HighlightVisitor
+       var v = new NitlightVisitor(mm, mmodules)
+       var prefix = opt_line_id_prefix.value
+       if prefix != null then
+               v.line_id_prefix = prefix.trim
+       end
+       v.include_loose_tokens = true
+       v.include_whole_lines = true
 
        if opt_first_line.value != 0 then v.first_line = opt_first_line.value
        if opt_last_line.value != 0 then v.last_line = opt_last_line.value
        if opt_ast.value then v.with_ast = true
+       if opt_noinfobox.value then v.show_infobox = false
        var page = null
-       var m = modelbuilder.mmodule2nmodule[mm]
+       var m = modelbuilder.mmodule2node(mm)
+       assert m != null
        if not opt_fragment.value then
                page = new HTMLTag("html")
                page.add_raw_html """<head>
@@ -71,23 +173,21 @@ for mm in mmodules do
                else
                        page.add_raw_html """<link rel="stylesheet" type="text/css" href="style.css" />"""
                end
-               page.add_raw_html """<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css">\n"""
-               page.add_raw_html "</head><body><pre>"
+               page.add_raw_html v.head_content
+               page.add_raw_html "</head><body><pre class='nit_code'>"
        end
-       v.enter_visit(m)
+       v.highlight_node(m)
        if not opt_fragment.value then
                page.add(v.html)
                page.add_raw_html "</pre>"
-               page.add_raw_html """<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>\n"""
-               page.add_raw_html """<script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>\n"""
-               page.add_raw_html """<script>$(".popupable").popover({html:true, placement:'top'})/*initialize bootstrap popover*/</script>\n"""
+               page.add_raw_html v.foot_content
                page.add_raw_html "</body>"
        else
                page = v.html
        end
 
        if dir != null then
-               page.write_to_file("{dir}/{mm.name}.html")
+               page.write_to_file("{dir}/{mm.c_name}.html")
        else
                page.write_to(stdout)
        end
@@ -106,15 +206,15 @@ if dir != null then
                var n2 = new HTMLTag("a")
                page.add n
                n.add n2
-               n2.attr("href", "{mm.name}.html")
-               n2.text(mm.name)
+               n2.attr("href", "{mm.c_name}.html")
+               n2.text(mm.full_name)
        end
        page.add_raw_html "</li></body>"
        page.write_to_file("{dir}/index.html")
 
-       var v = new HighlightVisitor
+       var v = new HtmlightVisitor
        toolcontext.info("write {dir}/style.css", 1)
-       var f = new OFStream.open("{dir}/style.css")
+       var f = new FileWriter.open("{dir}/style.css")
        f.write v.css_content
        f.close
 end