# 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
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_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_line_id_prefix, 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)
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
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.mmodule2node(mm)
assert m != null
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>"
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
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 FileWriter.open("{dir}/style.css")
f.write v.css_content