Propose that `;` is usable as a hard line break. While this is not really nit-ish, the only need is in fact to be able to write short one-line scripts in environment where linefeeds are not an option.
~~~sh
$ ./nit -e 'for line in stdin.each_line do; var xs = line.split(":"); if xs.not_empty then print xs.first; end' < /etc/passwd
~~~
Pull-Request: #1305
Reviewed-by: Alexandre Terrasa <alexandre@moz-code.org>
Reviewed-by: Alexis Laferrière <alexis.laf@xymus.net>
Reviewed-by: Lucas Bajolet <r4pass@hotmail.com>
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Sample module showing the use of the i18n annotation
+module langannot is i18n
+
+import gettext
+
+class X
+ fun foo: String do
+ return "This String is a test"
+ end
+end
+
+var t = new X
+print t.foo
+
+print "This String is a test"
+
+print """Multiline string
+
+example
+
+
+of the language annotation capacities
+"""
--- /dev/null
+#: langannot::langannot 22--10:32, langannot::langannot 29--7:29
+msgid "This String is a test"
+msgstr "This String is a test"
+
+#: langannot::langannot 31--7:3
+msgid "Multiline string\n\nexample\n\n\nof the language annotation capacities\n"
+msgstr "Multiline string\n\nexample\n\n\nof the language annotation capacities\n"
+
+# Generated file, do not modify
--- /dev/null
+#: langannot::langannot 22--10:32, langannot::langannot 29--7:29
+msgid "This String is a test"
+msgstr "Cette chaîne de caractères est un test"
+
+#: langannot::langannot 31--7:3
+msgid "Multiline string\n\nexample\n\n\nof the language annotation capacities\n"
+msgstr "Example de\n\nchaine multiligne\n\n\navec annotation de localisation\n"
+
+# Generated file, do not modify
--- /dev/null
+#: langannot::langannot 22--10:32, langannot::langannot 29--7:29
+msgid "This String is a test"
+msgstr "この文字列はてストです"
+
+#: langannot::langannot 31--7:3
+msgid "Multiline string\n\nexample\n\n\nof the language annotation capacities\n"
+msgstr "複数行の文字列\n\nなサンプルプログラム\n\n\n新しい国際化アノテーションとともに\n"
+
+# Generated file, do not modify
--- /dev/null
+#: langannot::langannot 22--10:32, langannot::langannot 29--7:29
+msgid "This String is a test"
+msgstr ""
+
+#: langannot::langannot 31--7:3
+msgid "Multiline string\n\nexample\n\n\nof the language annotation capacities\n"
+msgstr ""
+
+# Generated file, do not modify
--- /dev/null
+#!/usr/bin/env nit
+#
+# This file is part of NIT ( http://www.nitlanguage.org ).
+# This program is public domain
+
+# Task: Balanced brackets
+# SEE: <http://rosettacode.org/wiki/Balanced_brackets>
+module balanced_brackets
+
+# Are `[` and `]` balanced?
+# Other characters are ignored.
+#
+# assert is_balanced("[][[]]")
+# assert is_balanced("")
+# assert not is_balanced("[[]")
+# assert not is_balanced("][][")
+fun is_balanced(s: String): Bool
+do
+ var l = 0
+ for x in s.chars do
+ if x == '[' then
+ l += 1
+ else if x == ']' then
+ l -= 1
+ if l < 0 then return false
+ end
+ end
+ return l == 0
+end
+
+var n = 3
+if args.not_empty then n = args.first.to_i
+
+for i in [0..10[ do
+ var a = (['[', ']'] * n)
+ a.shuffle
+ var b = a.join("")
+ if is_balanced(b) then print "{b} is well-balanced" else print "{b} is not well-balanced"
+end
# Bucket type used in this implementation.
type BUCKET: HashSet[Bucketable[G]]
- private var buckets: Array[BUCKET] is noinit
-
private var next_bucket: nullable BUCKET = null
private var current_bucket_key: Int = -1
- init
- do
- var n_buckets = 100
- buckets = new Array[BUCKET].with_capacity(n_buckets)
+ # Number of `buckets`, default at 100
+ #
+ # Must be set prior to using any other methods of this class.
+ var n_buckets = 100
- for b in [0 .. n_buckets [do
- buckets[b] = new HashSet[Bucketable[G]]
- end
- end
+ private var buckets: Array[BUCKET] =
+ [for b in n_buckets.times do new HashSet[Bucketable[G]]] is lazy
# Add the Bucketable event `e` at `at_tick`.
fun add_at(e: Bucketable[G], at_tick: Int)
--- /dev/null
+# This file is part of NIT (http://www.nitlanguage.org).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Internationalization of Strings using `gettext` library
+module gettext is
+ new_annotation i18n
+end
+
+in "C" `{
+ #include <libintl.h>
+ #include <locale.h>
+`}
+
+redef class Sys
+ redef fun run do
+ "".to_cstring.set_locale
+ super
+ end
+end
+
+redef class NativeString
+ # Sets the locale of the program running
+ #
+ # This can be set at different times in the program,
+ # if used with an empty string, the locale will
+ # be set to the user's environment locale.
+ #
+ # For more info, SEE setlocale manual
+ fun set_locale `{
+ setlocale(LC_ALL, recv);
+ `}
+end
+
+redef class String
+ # Gets the translation of `self` via gettext from `dir` using `domain`
+ #
+ # `domain`: Gettext domain, i.e. file/module name
+ # `dir`: Where the locale/LC_MESSAGES folder for this domain is located
+ fun get_translation(domain, dir: String): String do
+ bindtextdomain(domain, dir)
+ return dgettext(domain)
+ end
+
+ # Gettext `gettext`, SEE gettext manual for further info
+ fun gettext: String
+ import String.to_cstring, NativeString.to_s `{
+ return NativeString_to_s(gettext(String_to_cstring(recv)));
+ `}
+
+ # Gettext `dgettext`, SEE gettext manual for further info
+ fun dgettext(domain: String): String
+ import String.to_cstring, NativeString.to_s `{
+ return NativeString_to_s(dgettext(String_to_cstring(domain), String_to_cstring(recv)));
+ `}
+end
+
+# Gettext `bindtextdomain`, SEE gettext manual for further info
+fun bindtextdomain(domain, dir: String) import String.to_cstring `{
+ bindtextdomain(String_to_cstring(domain), String_to_cstring(dir));
+`}
+
+# Gettext `textdomain`, SEE gettext manual for further info
+fun textdomain(domain: String) import String.to_cstring `{
+ textdomain(String_to_cstring(domain));
+`}
# Pops the current local reference frame and return a valid reference to self
#
- # Similiar to `JavaVM::pop_local_frame` but returns a value.
+ # Similar to `JavaVM::pop_local_frame` but returns a value.
fun pop_from_local_frame: SELF
do
var jni_env = sys.jni_env
# In order to reproduce executions, the behavior of the application must be deterministic
# for a given sequence of inputs.
# The main source of differences in executions is caused by the `rand` function,
-# Set the environment variable `MNIT_SRAND` to a value to force srand to be initialized with this value.
+# Set the environment variable `NIT_SRAND` to a value to force srand to be initialized with this value.
#
# The input event file is made of event descriptions, one event by line.
#
redef fun setup
do
- var env = "MNIT_SRAND".environ
- if env != "" then
- srand_from(env.to_i)
- else
- srand_from(0)
- end
-
var input = "MNIT_READ_INPUT".environ
if input != "" then
injected_input_stream = new FileReader.open(input)
end
end
-# Instances of the Iterator class generates a series of elements, one at a time.
-# They are mainly used with collections.
+# Iterators generate a series of elements, one at a time.
+#
+# They are mainly used with collections and obtained from `Collection::iterator`.
interface Iterator[E]
# The current item.
# Require `is_ok`.
private fun get_environ: NativeString is extern "string_NativeString_NativeString_get_environ_0"
private fun setenv( v : NativeString ) is extern "string_NativeString_NativeString_setenv_1"
end
+
+redef class Sys
+ redef init
+ do
+ var x = "NIT_SRAND".environ
+ if x != "" then srand_from(x.to_i)
+ end
+end
redef class Collection[ E ]
# Return a random element form the collection
# There must be at least one element in the collection
+ #
+ # ~~~
+ # var x = [1,2,3].rand
+ # assert x == 1 or x == 2 or x == 3
+ # ~~~
fun rand: E
do
if is_empty then abort
end
abort
end
+
+ # Return a new array made of elements in a random order.
+ #
+ # ~~~
+ # var a = [1,2,1].to_shuffle
+ # assert a == [1,1,2] or a == [1,2,1] or a == [2,1,1]
+ # ~~~
+ fun to_shuffle: Array[E]
+ do
+ var res = self.to_a
+ res.shuffle
+ return res
+ end
end
redef class SequenceRead[E]
end
end
+redef class AbstractArray[E]
+ # Reorder randomly the elements in self.
+ #
+ # ~~~
+ # var a = new Array[Int]
+ #
+ # a.shuffle
+ # assert a.is_empty
+ #
+ # a.add 1
+ # a.shuffle
+ # assert a == [1]
+ #
+ # a.add 2
+ # a.shuffle
+ # assert a == [1,2] or a == [2,1]
+ # ~~~
+ #
+ # ENSURE self.shuffle.has_exactly(old(self))
+ fun shuffle
+ do
+ for i in [0..length[ do
+ var j = i + (length-i).rand
+ var tmp = self[i]
+ self[i] = self[j]
+ self[j] = tmp
+ end
+ end
+end
+
redef class Sys
init
do
redef fun read(i)
do
if last_error != null then return ""
- if _buffer.length == _buffer_pos then
- if not eof then
- return read(i)
- end
- return ""
- end
- if _buffer_pos + i >= _buffer.length then
- var from = _buffer_pos
- _buffer_pos = _buffer.length
- if from == 0 then return _buffer.to_s
- return _buffer.substring_from(from).to_s
+ if eof then return ""
+ var p = _buffer_pos
+ var bufsp = _buffer.length - p
+ if bufsp >= i then
+ _buffer_pos += i
+ return _buffer.substring(p, i).to_s
end
- _buffer_pos += i
- return _buffer.substring(_buffer_pos - i, i).to_s
+ _buffer_pos = _buffer.length
+ var readln = _buffer.length - p
+ var s = _buffer.substring(p, readln).to_s
+ fill_buffer
+ return s + read(i - readln)
end
redef fun read_all
redraw!
endfun
-" Activate the omnifunc on Nit files
-autocmd FileType nit set omnifunc=NitOmnifunc
+if !exists("g:nit_disable_omnifunc") || !g:nit_disable_omnifunc
+ " Activate the omnifunc on Nit files
+ autocmd FileType nit set omnifunc=NitOmnifunc
+endif
" Define the user command Nitdoc for ease of use
command -nargs=* Nitdoc call Nitdoc("<args>")
end
end
op.append("\}\n")
- return new GraphArticle(mentity, name, op)
+ return new GraphArticle(mentity, name, "Importation Graph", op)
end
end
end
end
op.append("\}\n")
- return new GraphArticle(mentity, name, op)
+ return new GraphArticle(mentity, name, "Inheritance Graph", op)
end
end
# Graph ID (used for outputing file with names).
var id: String
+ # Graph title to display.
+ var graph_title: String
+
# Dot script of the graph.
var dot: Text
end
end
- # A source link template for a given location
- fun tpl_showsource(location: nullable Location): nullable String
+ # Returns a HTML link for a given `location`.
+ fun html_source_link(location: nullable Location): nullable String
do
if location == null then return null
var source = ctx.opt_source.value
# build page
init_title(v, doc)
- init_sidebar(v, doc)
init_topmenu(v, doc)
init_content(v, doc)
+ init_sidebar(v, doc)
# piwik tracking
var tracker_url = v.ctx.opt_piwik_tracker.value
# Build page sidebar if any.
fun init_sidebar(v: RenderHTMLPhase, doc: DocModel) do
- sidebar = new TplSidebar
+ sidebar = new DocSideBar
+ sidebar.boxes.add new DocSideBox("Summary", html_toc)
end
# Build page content template.
- fun init_content(v: RenderHTMLPhase, doc: DocModel) do end
+ fun init_content(v: RenderHTMLPhase, doc: DocModel) do
+ root.init_html_render(v, doc, self)
+ end
end
redef class OverviewPage
title = v.ctx.opt_custom_title.value.to_s
end
end
-
- # TODO this should be done in StructurePhase.
- redef fun init_content(v, doc) do
- # intro text
- var section = new TplSection.with_title("overview", title)
- var article = new TplArticle("intro")
- if v.ctx.opt_custom_intro.value != null then
- article.content = v.ctx.opt_custom_intro.value.to_s
- end
- section.add_child article
- # Projects list
- var mprojects = doc.model.mprojects.to_a
- var sorter = new MConcernRankSorter
- sorter.sort mprojects
- var ssection = new TplSection.with_title("projects", "Projects")
- for mproject in mprojects do
- var sarticle = mproject.tpl_article
- sarticle.subtitle = mproject.html_declaration
- sarticle.content = mproject.tpl_definition
- var comment = mproject.html_short_comment
- if comment != null then
- sarticle.content = comment
- end
- ssection.add_child sarticle
- end
- section.add_child ssection
- self.add_section section
- end
-
- redef fun init_sidebar(v, doc) do sidebar = new TplSidebar
end
redef class SearchPage
end
redef fun init_sidebar(v, doc) do end
-
- # TODO this should be done in StructurePhase.
- redef fun init_content(v, doc) do
- var tpl = new TplSearchPage("search_all")
- var section = new TplSection("search")
- # title
- tpl.title = "Index"
- # modules list
- for mmodule in modules_list(v, doc) do
- tpl.modules.add mmodule.html_link
- end
- # classes list
- for mclass in classes_list(v, doc) do
- tpl.classes.add mclass.html_link
- end
- # properties list
- for mproperty in mprops_list(v, doc) do
- var m = new Template
- m.add mproperty.intro.html_link
- m.add " ("
- m.add mproperty.intro.mclassdef.mclass.html_link
- m.add ")"
- tpl.props.add m
- end
- section.add_child tpl
- self.add_section section
- end
-
- # Extract mmodule list to display (sorted by name)
- private fun modules_list(v: RenderHTMLPhase, doc: DocModel): Array[MModule] do
- var sorted = new Array[MModule]
- for mmodule in doc.model.mmodule_importation_hierarchy do
- if mmodule.is_fictive or mmodule.is_test_suite then continue
- sorted.add mmodule
- end
- v.name_sorter.sort(sorted)
- return sorted
- end
-
- # Extract mclass list to display (sorted by name)
- private fun classes_list(v: RenderHTMLPhase, doc: DocModel): Array[MClass] do
- var sorted = doc.mclasses.to_a
- v.name_sorter.sort(sorted)
- return sorted
- end
-
- # Extract mproperty list to display (sorted by name)
- private fun mprops_list(v: RenderHTMLPhase, doc: DocModel): Array[MProperty] do
- var sorted = doc.mproperties.to_a
- v.name_sorter.sort(sorted)
- return sorted
- end
end
redef class MEntityPage
redef var html_url is lazy do return mentity.nitdoc_url
redef fun init_title(v, doc) do title = mentity.html_name
- redef fun init_content(v, doc) do add_section root.start_rendering(v, doc, self)
end
# FIXME all clases below are roughly copied from `doc_pages` and adapted to new
mclasses.add_all intros
mclasses.add_all redefs
if mclasses.is_empty then return
- var list = new TplList.with_classes(["list-unstyled", "list-labeled"])
-
+ var list = new UnorderedList
+ list.css_classes.add "list-unstyled list-labeled"
var sorted = mclasses.to_a
v.name_sorter.sort(sorted)
for mclass in sorted do
list.add_li tpl_sidebar_item(mclass)
end
- sidebar.boxes.add new TplSideBox.with_content("All classes", list)
+ sidebar.boxes.add new DocSideBox("All classes", list)
+ sidebar.boxes.last.is_open = false
end
- private fun tpl_sidebar_item(def: MClass): TplListItem do
- var classes = def.intro.tpl_css_classes.to_a
+ private fun tpl_sidebar_item(def: MClass): ListItem do
+ var classes = def.intro.css_classes
if intros.has(def) then
classes.add "intro"
else
classes.add "redef"
end
var lnk = new Template
- lnk.add new TplLabel.with_classes(classes)
+ lnk.add new DocHTMLLabel.with_classes(classes)
lnk.add def.html_link
- return new TplListItem.with_content(lnk)
+ return new ListItem(lnk)
end
end
mclasses.add_all mentity.filter_intro_mclasses(v.ctx.min_visibility)
mclasses.add_all mentity.filter_redef_mclasses(v.ctx.min_visibility)
if mclasses.is_empty then return
- var list = new TplList.with_classes(["list-unstyled", "list-labeled"])
+ var list = new UnorderedList
+ list.css_classes.add "list-unstyled list-labeled"
var sorted = mclasses.to_a
v.name_sorter.sort(sorted)
for mclass in sorted do
list.add_li tpl_sidebar_item(mclass)
end
- sidebar.boxes.add new TplSideBox.with_content("All classes", list)
+ sidebar.boxes.add new DocSideBox("All classes", list)
+ sidebar.boxes.last.is_open = false
end
- private fun tpl_sidebar_item(def: MClass): TplListItem do
- var classes = def.intro.tpl_css_classes.to_a
+ private fun tpl_sidebar_item(def: MClass): ListItem do
+ var classes = def.intro.css_classes
if def.intro_mmodule == self.mentity then
classes.add "intro"
else
classes.add "redef"
end
var lnk = new Template
- lnk.add new TplLabel.with_classes(classes)
+ lnk.add new DocHTMLLabel.with_classes(classes)
lnk.add def.html_link
- return new TplListItem.with_content(lnk)
+ return new ListItem(lnk)
end
end
redef fun init_sidebar(v, doc) do
super
var by_kind = new PropertiesByKind.with_elements(mclass_inherited_mprops(v, doc))
- var summary = new TplList.with_classes(["list-unstyled"])
+ var summary = new UnorderedList
+ summary.css_classes.add "list-unstyled"
by_kind.sort_groups(v.name_sorter)
for g in by_kind.groups do tpl_sidebar_list(g, summary)
- sidebar.boxes.add new TplSideBox.with_content("All properties", summary)
+ sidebar.boxes.add new DocSideBox("All properties", summary)
+ sidebar.boxes.last.is_open = false
end
- private fun tpl_sidebar_list(mprops: PropertyGroup[MProperty], summary: TplList) do
+ private fun tpl_sidebar_list(mprops: PropertyGroup[MProperty], summary: UnorderedList) do
if mprops.is_empty then return
- var entry = new TplListItem.with_content(mprops.title)
- var list = new TplList.with_classes(["list-unstyled", "list-labeled"])
+ var list = new UnorderedList
+ list.css_classes.add "list-unstyled list-labeled"
for mprop in mprops do
list.add_li tpl_sidebar_item(mprop)
end
- entry.append list
- summary.elts.add entry
+ var content = new Template
+ content.add mprops.title
+ content.add list
+ var li = new ListItem(content)
+ summary.add_li li
end
- private fun tpl_sidebar_item(mprop: MProperty): TplListItem do
- var classes = mprop.intro.tpl_css_classes.to_a
+ private fun tpl_sidebar_item(mprop: MProperty): ListItem do
+ var classes = mprop.intro.css_classes
if not mprop_is_local(mprop) then
classes.add "inherit"
var cls_url = mprop.intro.mclassdef.mclass.nitdoc_url
- var def_url = "{cls_url}#{mprop.nitdoc_id}"
- var lnk = new TplLink(def_url, mprop.html_name)
+ var def_url = "{cls_url}#article:{mprop.nitdoc_id}.definition"
+ var lnk = new Link(def_url, mprop.html_name)
var mdoc = mprop.intro.mdoc_or_fallback
if mdoc != null then lnk.title = mdoc.short_comment
var item = new Template
- item.add new TplLabel.with_classes(classes)
+ item.add new DocHTMLLabel.with_classes(classes)
item.add lnk
- return new TplListItem.with_content(item)
+ return new ListItem(item)
end
if mpropdefs.has(mprop.intro) then
classes.add "intro"
else
classes.add "redef"
end
+ var def = select_mpropdef(mprop)
+ var anc = def.html_link_to_anchor
+ anc.href = "#article:{def.nitdoc_id}.definition"
var lnk = new Template
- lnk.add new TplLabel.with_classes(classes)
- lnk.add mprop.html_link_to_anchor
- return new TplListItem.with_content(lnk)
+ lnk.add new DocHTMLLabel.with_classes(classes)
+ lnk.add anc
+ return new ListItem(lnk)
+ end
+
+ # Get the mpropdef contained in `self` page for a mprop.
+ #
+ # FIXME this method is used to translate a mprop into a mpropdefs for
+ # section linking. A better page structure should avoid this...
+ private fun select_mpropdef(mprop: MProperty): MPropDef do
+ for mclassdef in mentity.mclassdefs do
+ for mpropdef in mclassdef.mpropdefs do
+ if mpropdef.mproperty == mprop then return mpropdef
+ end
+ end
+ abort # FIXME is there a case where the prop is not found?
end
private fun mclass_inherited_mprops(v: RenderHTMLPhase, doc: DocModel): Set[MProperty] do
end
redef class DocComposite
- # Render this DocComposite as HTML.
+ # Prepares the HTML rendering for this element.
#
- # FIXME needed to maintain TplSection compatibility.
- fun render(v: RenderHTMLPhase, doc: DocModel, page: MEntityPage, parent: TplSectionElt) is abstract
+ # This visit is mainly used to set template attributes before rendering.
+ fun init_html_render(v: RenderHTMLPhase, doc: DocModel, page: DocPage) do
+ for child in children do child.init_html_render(v, doc, page)
+ end
end
-redef class DocRoot
-
- # Start the rendering from root.
- #
- # FIXME needed to maintain TplSection compatibility.
- fun start_rendering(v: RenderHTMLPhase, doc: DocModel, page: MEntityPage): TplSection do
- var section = new TplSection("top")
- var mentity = page.mentity
- section.title = mentity.html_name
- section.subtitle = mentity.html_declaration
- # FIXME ugly hack to avoid diff
+# FIXME hideous hacks to avoid diff
+redef class MEntitySection
+ redef fun init_html_render(v, doc, page) do
+ if not page isa MEntityPage then return
+ var mentity = self.mentity
if mentity isa MGroup and mentity.is_root then
- section.title = mentity.mproject.html_name
- section.subtitle = mentity.mproject.html_declaration
+ html_title = mentity.mproject.html_name
+ html_subtitle = mentity.mproject.html_declaration
else if mentity isa MProperty then
- section.title = "{mentity.html_name}{mentity.intro.html_signature.write_to_string}"
- section.subtitle = mentity.html_namespace
- section.summary_title = mentity.html_name
- end
- render(v, doc, page, section)
- return section
- end
-
- redef fun render(v, doc, page, parent) do
- for child in children do
- child.render(v, doc, page, parent)
+ var title = new Template
+ title.add mentity.html_name
+ title.add mentity.html_signature
+ html_title = title
+ html_subtitle = mentity.html_namespace
+ toc_title = mentity.html_name
end
+ super
end
end
+# FIXME hideous hacks to avoid diff
redef class ConcernSection
- redef fun render(v, doc, page, parent) do
- var section = new TplSection(mentity.nitdoc_id)
+ redef fun init_html_render(v, doc, page) do
+ if not page isa MEntityPage then return
var mentity = self.mentity
- # FIXME hideous hacks to avoid diff
- if page.mentity isa MModule and mentity isa MModule then
- render_concern_mmodule(page, section, mentity)
- else if page.mentity isa MClass and mentity isa MModule then
- render_concern_other(page, section, mentity)
- else if page.mentity isa MProperty and mentity isa MModule then
- render_concern_other(page, section, mentity)
- end
- for child in children do
- child.render(v, doc, page, section)
- end
- parent.add_child section
- end
-
- private fun render_concern_mmodule(page: MEntityPage, section: TplSection, mmodule: MModule) do
- var title = new Template
- if mmodule == page.mentity then
+ if page isa MGroupPage then
+ html_title = null
+ toc_title = mentity.html_name
+ is_toc_hidden = false
+ else if page.mentity isa MModule and mentity isa MModule then
+ var title = new Template
+ if mentity == page.mentity then
+ title.add "in "
+ toc_title = "in {mentity.html_name}"
+ else
+ title.add "from "
+ toc_title = "from {mentity.html_name}"
+ end
+ title.add mentity.html_namespace
+ html_title = title
+ else if (page.mentity isa MClass and mentity isa MModule) or
+ (page.mentity isa MProperty and mentity isa MModule) then
+ var title = new Template
title.add "in "
- section.summary_title = "in {mmodule.html_name}"
- else
- title.add "from "
- section.summary_title = "from {mmodule.html_name}"
+ title.add mentity.html_namespace
+ html_title = title
+ toc_title = "in {mentity.html_name}"
end
- title.add mmodule.html_namespace
- section.title = title
- end
-
- private fun render_concern_other(page: MEntityPage, section: TplSection, mmodule: MModule) do
- var title = new Template
- title.add "in "
- title.add mmodule.html_namespace
- section.title = title
- section.summary_title = "in {mmodule.html_name}"
- end
-end
-
-redef class MEntitySection
- redef fun render(v, doc, page, parent) do
- for child in children do child.render(v, doc, page, parent)
+ super
end
end
+# TODO redo showlink
redef class IntroArticle
- redef fun render(v, doc, page, parent) do
- var article = new TplArticle("intro")
+ redef fun init_html_render(v, doc, page) do
var mentity = self.mentity
if mentity isa MModule then
- article.source_link = v.tpl_showsource(mentity.location)
+ html_source_link = v.html_source_link(mentity.location)
else if mentity isa MClassDef then
- article.source_link = v.tpl_showsource(mentity.location)
+ html_source_link = v.html_source_link(mentity.location)
else if mentity isa MPropDef then
- article.source_link = v.tpl_showsource(mentity.location)
+ html_source_link = v.html_source_link(mentity.location)
end
- # article.subtitle = mentity.html_declaration
- # FIXME diff hack
- if mentity isa MProperty then
- # intro title
- var ns = mentity.intro.mclassdef.mmodule.html_namespace
- var section = new TplSection("intro")
- var title = new Template
- title.add "Introduction in "
- title.add ns
- section.title = title
- section.summary_title = "Introduction"
- var intro = mentity.intro.tpl_article
- intro.source_link = v.tpl_showsource(mentity.intro.location)
- section.add_child intro
- parent.add_child section
- else
- article.content = mentity.tpl_definition
- parent.add_child article
- end
- end
-end
-
-redef class ConcernsArticle
- redef fun render(v, doc, page, parent) do
- # FIXME diff hack
- var title = "concerns"
- if page.mentity isa MProperty then title = "Concerns"
- parent.add_child new TplArticle.
- with_content(title, "Concerns", concerns.to_tpl)
end
end
+# FIXME less hideous hacks...
redef class DefinitionArticle
- redef fun render(v, doc, page, parent) do
- var article: TplArticle
+ redef fun init_html_render(v, doc, page) do
var mentity = self.mentity
- # FIXME hideous hacks...
- if mentity isa MModule then
- article = mentity.tpl_article
- article.subtitle = mentity.html_declaration
- article.content = mentity.tpl_definition
+ if mentity isa MProject or mentity isa MModule then
+ var title = new Template
+ title.add mentity.html_icon
+ title.add mentity.html_namespace
+ html_title = title
+ toc_title = mentity.html_name
+ if mentity isa MModule then
+ html_source_link = v.html_source_link(mentity.location)
+ end
else if mentity isa MClass then
- article = make_mclass_article(v, page)
+ var title = new Template
+ title.add mentity.html_icon
+ title.add mentity.html_link
+ html_title = title
+ html_subtitle = mentity.html_namespace
+ toc_title = mentity.html_name
+ is_no_body = true
else if mentity isa MClassDef then
- article = make_mclassdef_article(v, page)
- article.source_link = v.tpl_showsource(mentity.location)
- else if mentity isa MPropDef and page.mentity isa MClass then
- article = make_mpropdef_article(v, doc, page)
- else
- article = mentity.tpl_article
- article.subtitle = mentity.html_declaration
- if mentity isa MPropDef then
- article.source_link = v.tpl_showsource(mentity.location)
- end
- end
- for child in children do
- child.render(v, doc, page, article)
- end
- parent.add_child article
- end
-
- # FIXME avoid diff while preserving TplArticle compatibility.
-
- private fun make_mclass_article(v: RenderHTMLPhase, page: MEntityPage): TplArticle do
- var article = mentity.tpl_article
- article.subtitle = mentity.html_namespace
- article.content = null
- return article
- end
-
- private fun make_mclassdef_article(v: RenderHTMLPhase, page: MEntityPage): TplArticle do
- var mclassdef = mentity.as(MClassDef)
- var article = mentity.tpl_article
- if mclassdef.is_intro and mclassdef.mmodule != page.mentity then
- article = mentity.tpl_short_article
- end
- var title = new Template
- title.add "in "
- title.add mclassdef.mmodule.html_namespace
- article.subtitle = title
- return article
- end
-
- private fun make_mpropdef_article(v: RenderHTMLPhase, doc: DocModel, page: MEntityPage): TplArticle
- do
- var mpropdef = mentity.as(MPropDef)
- var mprop = mpropdef.mproperty
- var article = new TplArticle(mprop.nitdoc_id)
- var title = new Template
- title.add mprop.tpl_icon
- title.add "<span id='{mpropdef.nitdoc_id}'></span>"
- if mpropdef.is_intro then
- title.add mprop.html_link
- title.add mprop.intro.html_signature
- else
- var cls_url = mprop.intro.mclassdef.mclass.nitdoc_url
- var def_url = "{cls_url}#{mprop.nitdoc_id}"
- var lnk = new TplLink.with_title(def_url, mprop.html_name,
- "Go to introduction")
- title.add "redef "
- title.add lnk
- end
- article.title = title
- article.title_classes.add "signature"
- article.summary_title = "{mprop.html_name}"
- article.subtitle = mpropdef.html_namespace
- var comment = mpropdef.html_comment
- if comment != null then
- article.content = comment
- end
- # TODO move in its own phase? let's see after doc_template refactoring.
- # Add linearization
- var all_defs = new HashSet[MPropDef]
- for local_def in local_defs(page.as(MClassPage), mprop) do
- all_defs.add local_def
- var smpropdef = local_def
- while not smpropdef.is_intro do
- smpropdef = smpropdef.lookup_next_definition(
- doc.mainmodule, smpropdef.mclassdef.bound_mtype)
- all_defs.add smpropdef
- end
- end
- var lin = all_defs.to_a
- doc.mainmodule.linearize_mpropdefs(lin)
- if lin.length > 1 then
- var lin_article = new TplArticle("{mpropdef.nitdoc_id}.lin")
- lin_article.title = "Inheritance"
- var lst = new TplList.with_classes(["list-unstyled", "list-labeled"])
- for smpropdef in lin do
- lst.add_li smpropdef.tpl_inheritance_item
+ var title = new Template
+ title.add "in "
+ title.add mentity.mmodule.html_namespace
+ html_title = mentity.html_declaration
+ html_subtitle = title
+ toc_title = "in {mentity.html_name}"
+ html_source_link = v.html_source_link(mentity.location)
+ if page isa MEntityPage and mentity.is_intro and mentity.mmodule != page.mentity then
+ is_short_comment = true
end
- lin_article.content = lst
- article.add_child lin_article
- end
- return article
- end
-
- # Filter `page.mpropdefs` for this `mpropertie`.
- #
- # FIXME compatability with current templates.
- private fun local_defs(page: MClassPage, mproperty: MProperty): HashSet[MPropDef] do
- var mpropdefs = new HashSet[MPropDef]
- for mpropdef in page.mpropdefs do
- if mpropdef.mproperty == mproperty then
- mpropdefs.add mpropdef
+ if page isa MModulePage then is_toc_hidden = true
+ else if mentity isa MPropDef then
+ if page isa MClassPage then
+ var title = new Template
+ title.add mentity.html_icon
+ title.add mentity.html_declaration
+ html_title = title
+ html_subtitle = mentity.html_namespace
+ toc_title = mentity.html_name
+ else
+ var title = new Template
+ title.add "in "
+ title.add mentity.mclassdef.html_link
+ html_title = title
+ toc_title = "in {mentity.mclassdef.html_name}"
end
+ html_source_link = v.html_source_link(mentity.location)
end
- return mpropdefs
- end
-end
-
-redef class IntrosRedefsListArticle
- redef fun render(v, doc, page, parent) do
- if mentities.is_empty then return
- var title = list_title
- # FIXME diff hack
- var id = "intros"
- if title == "Redefines" then id = "redefs"
- var article = new TplArticle.with_title("{mentity.nitdoc_id}.{id}", title)
- var list = new TplList.with_classes(["list-unstyled", "list-labeled"])
- for mentity in mentities do
- list.add_li mentity.tpl_list_item
- end
- article.content = list
- parent.add_child article
- end
-end
-
-# FIXME compatibility with doc_templates.
-redef class ImportationListSection
- redef fun render(v, doc, page, parent) do
- var section = new TplSection.with_title("dependencies", "Dependencies")
- for child in children do
- child.render(v, doc, page, section)
- end
- parent.add_child section
- end
-end
-
-# FIXME compatibility with doc_templates.
-redef class InheritanceListSection
- redef fun render(v, doc, page, parent) do
- var section = new TplSection.with_title("inheritance", "Inheritance")
- for child in children do
- child.render(v, doc, page, section)
+ if page isa MGroupPage and mentity isa MModule then
+ is_toc_hidden = true
end
- parent.add_child section
+ super
end
end
-# FIXME compatibility with doc_templates.
-redef class HierarchyListArticle
- redef fun render(v, doc, page, parent) do
- if mentities.is_empty then return
- var title = list_title
- var id = list_title.to_lower
- var article = new TplArticle.with_title(id, title)
- var list = new TplList.with_classes(["list-unstyled", "list-definition"])
- for mentity in mentities do
- list.elts.add mentity.tpl_list_item
+redef class HomeArticle
+ redef fun init_html_render(v, doc, page) do
+ if v.ctx.opt_custom_title.value != null then
+ self.html_title = v.ctx.opt_custom_title.value.to_s
+ self.toc_title = v.ctx.opt_custom_title.value.to_s
end
- article.content = list
- parent.add_child article
+ self.content = v.ctx.opt_custom_intro.value
+ super
end
end
redef class GraphArticle
- redef fun render(v, doc, page, parent) do
+ redef fun init_html_render(v, doc, page) do
var output_dir = v.ctx.output_dir
var path = output_dir / id
var path_sh = path.escape_to_sh
file.close
sys.system("\{ test -f {path_sh}.png && test -f {path_sh}.s.dot && diff -- {path_sh}.dot {path_sh}.s.dot >/dev/null 2>&1 ; \} || \{ cp -- {path_sh}.dot {path_sh}.s.dot && dot -Tpng -o{path_sh}.png -Tcmapx -o{path_sh}.map {path_sh}.s.dot ; \}")
var fmap = new FileReader.open("{path}.map")
- var map = fmap.read_all
+ self.map = fmap.read_all
fmap.close
-
- var article = new TplArticle("graph")
- var alt = ""
- # FIXME diff hack
- # if title != null then
- # article.title = title
- # alt = "alt='{title.html_escape}'"
- # end
- article.css_classes.add "text-center"
- var content = new Template
- var name_html = id.html_escape
- content.add "<img src='{name_html}.png' usemap='#{name_html}' style='margin:auto' {alt}/>"
- content.add map
- article.content = content
- parent.add_child article
- end
-end
-
-redef class Location
- # Github url based on this location
- fun github(gitdir: String): String do
- var base_dir = getcwd.join_path(gitdir).simplify_path
- var file_loc = getcwd.join_path(file.filename).simplify_path
- var gith_loc = file_loc.substring(base_dir.length + 1, file_loc.length)
- return "{gith_loc}:{line_start},{column_start}--{line_end},{column_end}"
- end
-end
-
-redef class MEntity
- # A template article that briefly describe the entity
- fun tpl_short_article: TplArticle do
- var tpl = tpl_article
- var comment = html_short_comment
- if comment != null then
- tpl.content = comment
- end
- return tpl
- end
-
- # A template article that describe the entity
- fun tpl_article: TplArticle do
- var tpl = new TplArticle.with_title(nitdoc_id, tpl_title)
- tpl.title_classes.add "signature"
- tpl.subtitle = html_namespace
- tpl.summary_title = html_name
- return tpl
- end
-
- # A template definition of the mentity
- # include name, sysnopsys, comment and namespace
- fun tpl_definition: TplDefinition is abstract
-
- # A li element that can go in a list
- fun tpl_list_item: TplListItem do
- var lnk = new Template
- lnk.add new TplLabel.with_classes(tpl_css_classes)
- lnk.add html_link
- var comment = html_short_comment
- if comment != null then
- lnk.add ": "
- lnk.add comment
- end
- return new TplListItem.with_content(lnk)
- end
-
- var tpl_css_classes = new Array[String]
-
- # Box title for this mentity
- fun tpl_title: Template do
- var title = new Template
- title.add tpl_icon
- title.add html_namespace
- return title
- end
-
- # Icon that will be displayed before the title
- fun tpl_icon: TplIcon do
- var icon = new TplIcon.with_icon("tag")
- icon.css_classes.add_all(tpl_css_classes)
- return icon
- end
-end
-
-redef class MConcern
- # Return a li element for `self` that can be displayed in a concern list
- private fun tpl_concern_item: TplListItem do
- var lnk = new Template
- lnk.add html_link_to_anchor
- var comment = html_short_comment
- if comment != null then
- lnk.add ": "
- lnk.add comment
- end
- return new TplListItem.with_content(lnk)
- end
-end
-
-redef class MProject
- redef fun tpl_definition do
- var tpl = new TplDefinition
- var comment = html_comment
- if comment != null then
- tpl.comment = comment
- end
- return tpl
- end
-
- redef fun tpl_css_classes do return ["public"]
-end
-
-redef class MGroup
- redef fun tpl_definition do
- var tpl = new TplDefinition
- var comment = html_comment
- if comment != null then
- tpl.comment = comment
- end
- return tpl
- end
-end
-
-redef class MModule
- redef fun tpl_definition do
- var tpl = new TplClassDefinition
- var comment = html_comment
- if comment != null then
- tpl.comment = comment
- end
- return tpl
- end
-
- redef fun tpl_css_classes do return ["public"]
-end
-
-redef class MClass
- redef fun tpl_definition do return intro.tpl_definition
-
- redef fun tpl_title do
- var title = new Template
- title.add tpl_icon
- title.add html_link
- return title
- end
-
- redef fun tpl_icon do return intro.tpl_icon
- redef fun tpl_css_classes do return intro.tpl_css_classes
-end
-
-redef class MClassDef
- redef fun tpl_article do
- var tpl = new TplArticle(nitdoc_id)
- tpl.summary_title = "in {mmodule.html_name}"
- tpl.title = html_declaration
- tpl.title_classes.add "signature"
- var title = new Template
- title.add "in "
- title.add mmodule.html_namespace
- tpl.subtitle = title
- var comment = html_comment
- if comment != null then
- tpl.content = comment
- end
- return tpl
- end
-
- redef fun tpl_title do
- var title = new Template
- title.add tpl_icon
- title.add html_link
- return title
- end
-
- redef fun tpl_definition do
- var tpl = new TplClassDefinition
- var comment = html_comment
- if comment != null then
- tpl.comment = comment
- end
- return tpl
- end
-
- redef fun tpl_css_classes do
- var set = new HashSet[String]
- if is_intro then set.add "intro"
- for m in mclass.intro.modifiers do set.add m.to_cmangle
- for m in modifiers do set.add m.to_cmangle
- return set.to_a
- end
-
- fun tpl_modifiers: Template do
- var tpl = new Template
- for modifier in modifiers do
- if modifier == "public" then continue
- tpl.add "{modifier.html_escape} "
- end
- return tpl
- end
-end
-
-redef class MProperty
- redef fun tpl_title do return intro.tpl_title
- redef fun tpl_icon do return intro.tpl_icon
- redef fun tpl_css_classes do return intro.tpl_css_classes
-end
-
-redef class MPropDef
- redef fun tpl_article do
- var tpl = new TplArticle(nitdoc_id)
- tpl.summary_title = "in {mclassdef.html_name}"
- var title = new Template
- title.add "in "
- title.add mclassdef.html_link
- tpl.title = title
- tpl.subtitle = html_declaration
- var comment = html_comment
- if comment != null then
- tpl.content = comment
- end
- return tpl
- end
-
- redef fun tpl_definition do
- var tpl = new TplDefinition
- var comment = html_comment
- if comment != null then
- tpl.comment = comment
- end
- return tpl
- end
-
- redef fun tpl_css_classes do
- var set = new HashSet[String]
- if is_intro then set.add "intro"
- for m in mproperty.intro.modifiers do set.add m.to_cmangle
- for m in modifiers do set.add m.to_cmangle
- return set.to_a
- end
-
- fun tpl_modifiers: Template do
- var tpl = new Template
- for modifier in modifiers do
- if modifier == "public" then continue
- tpl.add "{modifier.html_escape} "
- end
- return tpl
- end
-
- redef fun tpl_list_item do
- var lnk = new Template
- lnk.add new TplLabel.with_classes(tpl_css_classes.to_a)
- var atext = html_link.text
- var ahref = "{mclassdef.mclass.nitdoc_url}#{mproperty.nitdoc_id}"
- var atitle = html_link.title
- var anchor = new Link.with_title(ahref, atext, atitle)
- lnk.add anchor
- var comment = html_short_comment
- if comment != null then
- lnk.add ": "
- lnk.add comment
- end
- return new TplListItem.with_content(lnk)
- end
-
- fun tpl_inheritance_item: TplListItem do
- var lnk = new Template
- lnk.add new TplLabel.with_classes(tpl_css_classes.to_a)
- lnk.add mclassdef.mmodule.html_namespace
- lnk.add "::"
- var atext = mclassdef.html_link.text
- var ahref = "{mclassdef.mclass.nitdoc_url}#{mproperty.nitdoc_id}"
- var atitle = mclassdef.html_link.title
- var anchor = new Link.with_title(ahref, atext, atitle)
- lnk.add anchor
- var comment = html_short_comment
- if comment != null then
- lnk.add ": "
- lnk.add comment
- end
- var li = new TplListItem.with_content(lnk)
- li.css_classes.add "signature"
- return li
- end
-end
-
-redef class ConcernsTree
-
- private var seen = new HashSet[MConcern]
-
- redef fun add(p, e) do
- if seen.has(e) then return
- seen.add e
- super(p, e)
- end
-
- fun to_tpl: TplList do
- var lst = new TplList.with_classes(["list-unstyled", "list-definition"])
- for r in roots do
- var li = r.tpl_concern_item
- lst.add_li li
- build_list(r, li)
- end
- return lst
- end
-
- private fun build_list(e: MConcern, li: TplListItem) do
- if not sub.has_key(e) then return
- var subs = sub[e]
- var lst = new TplList.with_classes(["list-unstyled", "list-definition"])
- for e2 in subs do
- if e2 isa MGroup and e2.is_root then
- build_list(e2, li)
- else
- var sli = e2.tpl_concern_item
- lst.add_li sli
- build_list(e2, sli)
- end
- end
- li.append lst
- end
-end
-
-redef class MInnerClassDef
- redef fun tpl_definition do
- var tpl = new TplClassDefinition
- var comment = html_comment
- if comment != null then
- tpl.comment = comment
- end
- return tpl
end
end
if not doc.mpropdefs.has(mpropdef) then continue
var full_name = mpropdef.mclassdef.mclass.full_name
var cls_url = mpropdef.mclassdef.mclass.nitdoc_url
- var def_url = "{cls_url}#{mpropdef.mproperty.nitdoc_id}"
+ var def_url = "{cls_url}#article:{mpropdef.nitdoc_id}.definition"
add_result_for(mproperty.name, full_name, def_url)
end
end
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Add linearization lists to DefinitionArticle found in MClass pages.
+module doc_lin
+
+import doc_structure
+
+# LinPhase populates the DocPage content with linearization data.
+class LinListPhase
+ super DocPhase
+
+ # Used to sort list by linearization order
+ private var lin_sorter = new MEntityNameSorter
+
+ redef fun apply do
+ for page in doc.pages do page.apply_linearization(self, doc)
+ end
+end
+
+redef class DocPage
+
+ # Populates `self` with linearization data.
+ #
+ # See `LinListPhase`.
+ fun apply_linearization(v: LinListPhase, doc: DocModel) do end
+end
+
+redef class MClassPage
+ redef fun apply_linearization(v, doc) do
+ root.apply_linearization(v, doc, self)
+ end
+end
+
+redef class DocComposite
+
+ # Populates `self` with linearization data.
+ #
+ # For now, it's only used for mpropdefs linearization in MClassPage.
+ #
+ # See `LinListPhase`.
+ private fun apply_linearization(v: LinListPhase, doc: DocModel, page: DocPage) do
+ for child in children do child.apply_linearization(v, doc, page)
+ end
+end
+
+redef class DefinitionArticle
+ redef fun apply_linearization(v, doc, page) do
+ var mentity = self.mentity
+ if not mentity isa MPropDef then return
+ # Add linearization
+ var all_defs = new HashSet[MPropDef]
+ for local_def in local_defs(page.as(MClassPage), mentity.mproperty) do
+ all_defs.add local_def
+ var smpropdef = local_def
+ while not smpropdef.is_intro do
+ smpropdef = smpropdef.lookup_next_definition(
+ doc.mainmodule, smpropdef.mclassdef.bound_mtype)
+ all_defs.add smpropdef
+ end
+ end
+ var lin = all_defs.to_a
+ doc.mainmodule.linearize_mpropdefs(lin)
+ if lin.length > 1 then
+ add_child new DefinitionLinArticle(mentity, lin)
+ end
+ end
+
+ # Filter `page.mpropdefs` for this `mpropertie`.
+ #
+ # FIXME compatability with current templates.
+ private fun local_defs(page: MClassPage, mproperty: MProperty): HashSet[MPropDef] do
+ var mpropdefs = new HashSet[MPropDef]
+ for mpropdef in page.mpropdefs do
+ if mpropdef.mproperty == mproperty then
+ mpropdefs.add mpropdef
+ end
+ end
+ return mpropdefs
+ end
+end
+
+# Display a linearized list of definitions.
+class DefinitionLinArticle
+ super MEntityArticle
+
+ # The linearized list to display.
+ var mentities: Array[MEntity]
+end
# Populates the given DocModel.
redef fun apply do
- for page in doc.pages do
- if page isa MEntityPage then page.apply_structure(self, doc)
- end
+ for page in doc.pages do page.apply_structure(self, doc)
end
-
- # TODO index and search page should also be structured here
end
-redef class MEntityPage
+redef class DocPage
# Populates `self` with structure elements like DocComposite ones.
#
fun apply_structure(v: StructurePhase, doc: DocModel) do end
end
+redef class OverviewPage
+ redef fun apply_structure(v, doc) do
+ var article = new HomeArticle
+ root.add_child article
+ # Projects list
+ var mprojects = doc.model.mprojects.to_a
+ var sorter = new MConcernRankSorter
+ sorter.sort mprojects
+ var section = new ProjectsSection
+ for mproject in mprojects do
+ section.add_child new DefinitionArticle(mproject)
+ end
+ article.add_child section
+ end
+end
+
+redef class SearchPage
+ redef fun apply_structure(v, doc) do
+ var mmodules = doc.mmodules.to_a
+ v.name_sorter.sort(mmodules)
+ var mclasses = doc.mclasses.to_a
+ v.name_sorter.sort(mclasses)
+ var mprops = doc.mproperties.to_a
+ v.name_sorter.sort(mprops)
+ root.add_child new IndexArticle(mmodules, mclasses, mprops)
+ end
+end
+
redef class MGroupPage
redef fun apply_structure(v, doc) do
var section = new MEntitySection(mentity)
mentity.booster_rank = 0
section.add_child new ConcernsArticle(mentity, concerns)
for mentity in concerns do
+ var ssection = new ConcernSection(mentity)
if mentity isa MModule then
- section.add_child new DefinitionArticle(mentity)
- else
- section.add_child new ConcernSection(mentity)
+ ssection.add_child new DefinitionArticle(mentity)
end
+ section.add_child ssection
end
end
end
class DefinitionArticle
super MEntityArticle
end
+
+# The main project article.
+class HomeArticle
+ super DocArticle
+end
+
+# The project list.
+class ProjectsSection
+ super DocArticle
+end
+
+# An article that display an index of mmodules, mclasses and mproperties.
+class IndexArticle
+ super DocArticle
+
+ # List of mmodules to display.
+ var mmodules: Array[MModule]
+
+ # List of mclasses to display.
+ var mclasses: Array[MClass]
+
+ # List of mproperties to display.
+ var mprops: Array[MProperty]
+end
module html_components
import doc_base
-import template
+import html::bootstrap
import json::static
-#########################
-# general layout elements
-#########################
+# A label with a text content.
+class DocHTMLLabel
+ super BSLabel
-# A sidebar template
-class TplSidebar
- super Template
-
- # Sidebar contains sidebar element templates called boxes
- var boxes = new Array[TplSidebarElt]
-
- # Sort boxes by order priority
- private fun order_boxes do
- var sorter = new OrderComparator
- sorter.sort(boxes)
- end
-
- redef fun rendering do
- if boxes.is_empty then return
- order_boxes
- addn "<div id='sidebar'>"
- for box in boxes do add box
- addn "</div>"
- end
-end
-
-# Comparator used to sort boxes by order
-private class OrderComparator
- super Comparator
-
- redef type COMPARED: TplSidebarElt
-
- redef fun compare(a, b) do
- if a.order < b.order then return -1
- if a.order > b.order then return 1
- return 0
- end
-end
-
-# Something that can be put in the sidebar
-class TplSidebarElt
- super Template
-
- # Order of the box in the sidebar
- var order: Int = 1
-
- init with_order(order: Int) do self.order = order
-end
-
-# Agenericbox that can be added to sidebar
-class TplSideBox
- super TplSidebarElt
-
- # Title of the box to display
- # Title is also a placeholder for the collapse link
- var title: String
-
- # Box HTML id
- # equals to `title.to_cmangle` by default
- # Used for collapsing
- var id: String is noinit
-
- # Content to display in the box
- # box will not be rendered if the content is null
- var content: nullable Writable = null is writable
-
- # Is the box opened by default
- # otherwise, the user will have to clic on the title to display the content
- var is_open = false is writable
-
- init do
- self.id = title.to_cmangle
- end
-
- init with_content(title: String, content: Writable) do
- init(title)
- self.content = content
- end
-
- redef fun rendering do
- if content == null then return
- var open = ""
- if is_open then open = "in"
- addn "<div class='panel'>"
- addn " <div class='panel-heading'>"
- add " <a data-toggle='collapse' data-parent='#sidebar' data-target='#box_{id}' href='#'>"
- add title
- addn " </a>"
- addn " </div>"
- addn " <div id='box_{id}' class='panel-body collapse {open}'>"
- add content.as(not null)
- addn " </div>"
- addn "</div>"
- end
-end
-
-# Something that can go on a summary template
-class TplSummaryElt
- super Template
-
- # Add an element to the summary
- fun add_child(child: TplSummaryElt) is abstract
-end
-
-# A summary that can go on the sidebar
-# If the page contains a sidebar, the summary is automatically placed
-# on top of the sidebarauto-generated
-# summary contains anchors to all sections displayed in the page
-class TplSummary
- super TplSidebarElt
- super TplSummaryElt
-
- # Summary elements to display
- var children = new Array[TplSummaryElt]
-
- redef fun add_child(child) do children.add child
-
- redef fun rendering do
- if children.is_empty then return
- addn "<div class='panel'>"
- addn " <div class='panel-heading'>"
- add " <a data-toggle='collapse' data-parent='#sidebar' data-target='#box-sum' href='#'>"
- add "Summary"
- addn " </a>"
- addn " </div>"
- addn " <div id='box-sum' class='summary collapse in'>"
- addn " <ul class='nav'>"
- for entry in children do add entry
- addn " </ul>"
- addn " </div>"
- addn "</div>"
- end
-end
-
-# A summary entry
-class TplSummaryEntry
- super TplSummaryElt
-
- # Text to display
- var text: Writable
-
- # Children of this entry
- # Will be displayed as a tree
- var children = new Array[TplSummaryElt]
-
- redef fun add_child(child) do children.add child
-
- redef fun rendering do
- add "<li>"
- add text
- if not children.is_empty then
- addn "\n<ul class='nav'>"
- for entry in children do add entry
- addn "</ul>"
- end
- addn "</li>"
- end
-end
-
-# Something that can go in a section
-# Sections are automatically collected to populate the menu
-class TplSectionElt
- super Template
-
- # HTML anchor id
- var id: String
-
- # Title to display if any
- # if both `title` and `summary_title` are null then
- # the section will not appear in the summary
- var title: nullable Writable = null is writable
-
- # Subtitle to display if any
- var subtitle: nullable Writable = null is writable
-
- # Title that appear in the summary
- # if null use `title` instead
- var summary_title: nullable String = null is writable
-
- # CSS classes to apply on the section element
- var css_classes = new Array[String]
-
- # CSS classes to apply on the title heading element
- var title_classes = new Array[String]
-
- # Parent article/section if any
- var parent: nullable TplSectionElt = null
-
- init with_title(id: String, title: Writable) do
- init(id)
- self.title = title
- end
-
- # Level <hX> for HTML heading
- protected fun hlvl: Int do
- if parent == null then return 1
- return parent.hlvl + 1
- end
-
- # Elements contained by this section
- var children = new Array[TplSectionElt]
-
- # Add an element in this section
- fun add_child(child: TplSectionElt) do
- child.parent = self
- children.add child
- end
-
- # Is the section empty (no content at all)
- fun is_empty: Bool do return children.is_empty
-
- # Render this section in the summary
- fun render_summary(parent: TplSummaryElt) do
- if is_empty then return
- var title = summary_title
- if title == null and self.title != null then title = self.title.write_to_string
- if title == null then return
- var lnk = new TplLink("#{id}", title)
- var entry = new TplSummaryEntry(lnk)
- for child in children do
- child.render_summary(entry)
- end
- parent.add_child entry
- end
-end
-
-# A HTML <section> element
-class TplSection
- super TplSectionElt
-
- redef fun rendering do
- addn "<section id='{id}' class='{css_classes.join(" ")}'>"
- if title != null then
- var lvl = hlvl
- if lvl == 2 then title_classes.add "well well-sm"
- addn "<h{lvl} class='{title_classes.join(" ")}'>"
- addn title.as(not null)
- addn "</h{lvl}>"
- end
- if subtitle != null then
- addn "<div class='info subtitle'>"
- addn subtitle.as(not null)
- addn "</div>"
- end
- for child in children do
- add child
- end
- addn "</section>"
- end
-end
-
-# A page article that can go in a section
-class TplArticle
- super TplSectionElt
-
- # Content for this article
- var content: nullable Writable = null is writable
- var source_link: nullable Writable = null is writable
-
- init with_content(id: String, title: Writable, content: Writable) do
- with_title(id, title)
- self.content = content
- end
-
- redef fun render_summary(parent) do
- if is_empty then return
- var title = summary_title
- if title == null and self.title != null then title = self.title.write_to_string
- if title == null then return
- var lnk = new TplLink("#{id}", title)
- parent.add_child new TplSummaryEntry(lnk)
- end
-
- redef fun rendering do
- if is_empty then return
- addn "<article id='{id}' class='{css_classes.join(" ")}'>"
- if source_link != null then
- add "<div class='source-link'>"
- add source_link.as(not null)
- addn "</div>"
- end
- if title != null then
- var lvl = hlvl
- if lvl == 2 then title_classes.add "well well-sm"
- add "<h{lvl} class='{title_classes.join(" ")}'>"
- add title.as(not null)
- addn "</h{lvl}>"
- end
- if subtitle != null then
- add "<div class='info subtitle'>"
- add subtitle.as(not null)
- addn "</div>"
- end
- if content != null then
- add content.as(not null)
- end
- for child in children do
- add child
- end
- addn """</article>"""
- end
-
- redef fun is_empty: Bool do
- return title == null and subtitle == null and content == null and children.is_empty
- end
-end
-
-# A module / class / prop definition
-class TplDefinition
- super Template
-
- # Comment to display
- var comment: nullable Writable = null is writable
-
- # Namespace for this definition
- var namespace: nullable Writable = null is writable
-
- # Location link to display
- var location: nullable Writable = null is writable
-
- private fun render_info do
- addn "<div class='info text-right'>"
- if namespace != null then
- if comment == null then
- add "<span class=\"noComment\">no comment for </span>"
- end
- add namespace.as(not null)
- end
- if location != null then
- add " "
- add location.as(not null)
- end
- addn "</div>"
- end
-
- private fun render_comment do
- if comment != null then add comment.as(not null)
- end
-
- redef fun rendering do
- addn "<div class='definition'>"
- render_comment
- render_info
- addn "</div>"
- end
-end
-
-# Class definition
-class TplClassDefinition
- super TplDefinition
-
- var intros = new Array[TplListElt]
- var redefs = new Array[TplListElt]
-
- redef fun rendering do
- addn "<div class='definition'>"
- render_comment
- render_info
- render_list("Introduces", intros)
- render_list("Redefines", redefs)
- addn "</div>"
+ redef init do
+ css_classes.clear
+ css_classes.add "label"
end
- private fun render_list(name: String, elts: Array[TplListElt]) do
- if elts.is_empty then return
- addn "<h5>{name.html_escape}</h5>"
- addn "<ul class='list-unstyled list-definition'>"
- for elt in elts do add elt
- addn "</ul>"
- end
-end
-
-# Layout for Search page
-class TplSearchPage
- super TplSectionElt
-
- var modules = new Array[Writable]
- var classes = new Array[Writable]
- var props = new Array[Writable]
-
- redef fun rendering do
- var title = self.title
- if title != null then addn "<h1>{title.to_s.html_escape}</h1>"
- addn "<div class='container-fluid'>"
- addn " <div class='row'>"
- if not modules.is_empty then
- addn "<div class='col-xs-4'>"
- addn "<h3>Modules</h3>"
- addn "<ul>"
- for m in modules do
- add "<li>"
- add m
- addn "</li>"
- end
- addn "</ul>"
- addn "</div>"
- end
- if not classes.is_empty then
- addn "<div class='col-xs-4'>"
- addn "<h3>Classes</h3>"
- addn "<ul>"
- for c in classes do
- add "<li>"
- add c
- addn "</li>"
- end
- addn "</ul>"
- addn "</div>"
- end
- if not props.is_empty then
- addn "<div class='col-xs-4'>"
- addn "<h3>Properties</h3>"
- addn "<ul>"
- for p in props do
- add "<li>"
- add p
- addn "</li>"
- end
- addn "</ul>"
- addn "</div>"
- end
- addn " </div>"
- addn "</div>"
- end
-end
-
-#####################
-# Basiv HTML elements
-#####################
-
-# A html link <a>
-class TplLink
- super Template
-
- # Link href
- var href: String is writable
-
- # The raw HTML content to display in the link
- var text: Writable is writable
-
- # The unescaped optional title.
- var title: nullable String = null is writable
-
- init with_title(href, text, title: String) do
- init(href, text)
- self.title = title
- end
-
- redef fun rendering do
- add "<a href=\""
- add href.html_escape
- add "\""
- if title != null then
- add " title=\""
- add title.as(not null).html_escape
- add "\""
- end
- add ">"
- add text
- add "</a>"
- end
-end
-
-# A <ul> list
-class TplList
- super TplListElt
-
- # Elements contained in this list
- # can be <li> or <ul> elements
- var elts = new Array[TplListElt]
-
- # CSS classes of the <ul> element
- var css_classes = new Array[String]
-
- # Add content wrapped in a <li> element
- fun add_li(item: TplListItem) do elts.add item
-
- init with_classes(classes: Array[String]) do self.css_classes = classes
-
- fun is_empty: Bool do return elts.is_empty
-
- redef fun rendering do
- if elts.is_empty then return
- addn "<ul class='{css_classes.join(" ")}'>"
- for elt in elts do add elt
- addn "</ul>"
- end
-end
-
-# Something that can be added to a TplList
-class TplListElt
- super Template
-end
-
-# A list item <li>
-class TplListItem
- super TplListElt
-
- # Content of the list item
- var content = new Template
-
- # CSS classes of the <li> element
- var css_classes = new Array[String]
-
- init with_content(content: Writable) do append(content)
-
- init with_classes(content: Writable, classes: Array[String]) do
- with_content(content)
- css_classes = classes
- end
-
- # Append `content` to the item
- # similar to `self.content.add`
- fun append(content: Writable) do self.content.add content
-
- redef fun rendering do
- add "<li class='{css_classes.join(" ")}'>"
- add content
- addn "</li>"
- end
-end
-
-# A Bootstrap tab component that contains `TplTabPanel`.
-class TplTab
- super Template
-
- # Panels contained in the tab.
- var panels = new Array[TplTabPanel]
-
- # Add a new panel.
- fun add_panel(panel: TplTabPanel) do panels.add panel
-
- # CSS classes of the tab component.
- var css_classes = new Array[String]
-
- redef fun rendering do
- addn "<div class='tab-content'>"
- for panel in panels do add panel
- addn "</div>"
- end
-end
-
-# A panel that goes in a `TplTab`.
-class TplTabPanel
- super Template
-
- # CSS classes of the pane element.
- var css_classes = new Array[String]
-
- # The panel id.
- #
- # Used to show/hide panel.
- var id: String is noinit
-
- # The panel name.
- #
- # Displayed in the tab header or in the pointing link.
- var name: Writable
-
- # Is the panel visible by default?
- var is_active = false is writable
-
- # Body of the panel
- var content: nullable Writable = null is writable
-
- # Get a link pointing to this panel.
- fun tpl_link_to: Writable do
- var lnk = new Template
- lnk.add "<a data-target='#{id}' data-toggle='pill'>"
- lnk.add name
- lnk.add "</a>"
- return lnk
- end
-
- redef fun rendering do
- add "<div class='tab-pane {css_classes.join(" ")}"
- if is_active then add "active"
- addn "' id='{id}'>"
- if content != null then add content.as(not null)
- addn "</div>"
- end
-end
-
-# A label with a text content
-class TplLabel
- super Template
-
- # Content of the label if any
- var content: nullable Writable = null is writable
-
- # CSS classes of the <span> element
- var css_classes = new Array[String]
-
- init with_content(content: Writable) do self.content = content
- init with_classes(classes: Array[String]) do self.css_classes = classes
-
- redef fun rendering do
- add "<span class='label {css_classes.join(" ")}'>"
- if content != null then add content.as(not null)
- add "</span>"
- end
-end
-
-# A label with an icon
-class TplIcon
- super TplLabel
-
- # Bootsrap icon name
- # see: http://getbootstrap.com/components/#glyphicons
- var icon: String
-
- init with_icon(icon: String) do self.icon = icon
-
- redef fun rendering do
- add "<span class='glyphicon glyphicon-{icon} {css_classes.join(" ")}'>"
- if content != null then add content.as(not null)
- add "</span>"
+ # Init this label from css classes.
+ init with_classes(classes: Array[String]) do
+ init("label", "")
+ css_classes.add_all classes
end
end
end
end
-# Javacript template
+# Javacript template that can be added into a DocPage.
class TplScript
super Template
+ # HTML attributes to add in this tag.
var attrs = new Array[TagAttribute]
+
+ # Text content of this script tag.
var content: nullable Writable = null is writable
init do
attrs.add(new TagAttribute("type", "text/javascript"))
end
+ # Render the content of this script.
protected fun render_content do
if content != null then add content.as(not null)
end
class TplPiwikScript
super TplScript
+ # Piwik URL to use for this tracker.
var tracker_url: String
+
+ # Site ID used on Piwik system.
var site_id: String
redef fun render_content do
if mdoc == null then return null
return mdoc.tpl_short_comment
end
+
+ # Icon that will be displayed before the title
+ fun html_icon: BSIcon do
+ var icon = new BSIcon("tag")
+ icon.css_classes.add_all(css_classes)
+ return icon
+ end
+
+ # CSS classes used to decorate `self`.
+ #
+ # Mainly used for icons.
+ var css_classes = new Array[String]
+
+ # A li element that can go in a `HTMLList`.
+ fun html_list_item: ListItem do
+ var tpl = new Template
+ tpl.add new DocHTMLLabel.with_classes(css_classes)
+ tpl.add html_link
+ var comment = html_short_comment
+ if comment != null then
+ tpl.add ": "
+ tpl.add comment
+ end
+ return new ListItem(tpl)
+ end
end
redef class MProject
redef fun nitdoc_url do return root.nitdoc_url
redef var html_modifiers = ["project"]
redef fun html_namespace do return html_link
+ redef var css_classes = ["public"]
end
redef class MGroup
end
return tpl
end
+
+ redef var css_classes = ["public"]
end
redef class MModule
tpl.add html_link
return tpl
end
+
+ redef var css_classes = ["public"]
end
redef class MClass
# Returns `intro.html_signature`.
fun html_signature: Template do return intro.html_signature
+
+ redef fun html_icon do return intro.html_icon
+ redef fun css_classes do return intro.css_classes
end
redef class MClassDef
#
# For intro: `private abstract class Foo[E: Object]`
# For redef: `redef class Foo[E]`
- # TODO change the implementation to correspond to the comment.
redef fun html_declaration do
var tpl = new Template
tpl.add "<span>"
tpl.add html_modifiers.join(" ")
tpl.add " "
tpl.add html_link
- tpl.add html_signature
+ if is_intro then
+ tpl.add html_signature
+ else
+ tpl.add html_short_signature
+ end
tpl.add "</span>"
return tpl
end
end
return tpl
end
+
+ redef fun css_classes do
+ var set = new HashSet[String]
+ if is_intro then set.add "intro"
+ for m in mclass.intro.modifiers do set.add m.to_cmangle
+ for m in modifiers do set.add m.to_cmangle
+ return set.to_a
+ end
end
redef class MProperty
# Returns `intro.html_signature`.
fun html_signature: Template do return intro.html_signature
+
+ redef fun css_classes do return intro.css_classes
end
redef class MPropDef
#
# For intro: `private fun foo(e: Object): Bar is abstract`
# For redef: `redef fun foo(e) is cached`
- # TODO change the implementation to correspond to the comment.
redef fun html_declaration do
var tpl = new Template
tpl.add "<span>"
tpl.add html_modifiers.join(" ")
tpl.add " "
- tpl.add html_link
- tpl.add html_signature
+ if is_intro then
+ tpl.add html_link
+ tpl.add html_signature
+ else
+ tpl.add mproperty.intro.html_link
+ tpl.add html_short_signature
+ end
tpl.add "</span>"
return tpl
end
# Returns the MPropDef signature with static types.
fun html_signature: Template is abstract
+
+ redef fun css_classes do
+ var set = new HashSet[String]
+ if is_intro then set.add "intro"
+ for m in mproperty.intro.modifiers do set.add m.to_cmangle
+ for m in modifiers do set.add m.to_cmangle
+ return set.to_a
+ end
end
redef class MAttributeDef
end
end
+redef class ConcernsTree
+ # Render `self` as a hierarchical UnorderedList.
+ fun html_list: UnorderedList do
+ var lst = new UnorderedList
+ lst.css_classes.add "list-unstyled list-definition"
+ for r in roots do
+ var li = r.html_concern_item
+ lst.add_li li
+ build_html_list(r, li)
+ end
+ return lst
+ end
+
+ # Build the html list recursively.
+ private fun build_html_list(e: MConcern, li: ListItem) do
+ if not sub.has_key(e) then return
+ var subs = sub[e]
+ var lst = new UnorderedList
+ lst.css_classes.add "list-unstyled list-definition"
+ for e2 in subs do
+ if e2 isa MGroup and e2.is_root then
+ build_html_list(e2, li)
+ else
+ var sli = e2.html_concern_item
+ lst.add_li sli
+ build_html_list(e2, sli)
+ end
+ end
+ var text = new Template
+ text.add li.text
+ if not lst.is_empty then text.add lst
+ li.text = text
+ end
+end
+
+redef class MConcern
+ # Return a li element for `self` that can be displayed in a concern list
+ private fun html_concern_item: ListItem do
+ var lnk = html_link
+ var tpl = new Template
+ tpl.add new Link.with_title("#concern:{nitdoc_id}", lnk.text, lnk.title)
+ var comment = html_short_comment
+ if comment != null then
+ tpl.add ": "
+ tpl.add comment
+ end
+ return new ListItem(tpl)
+ end
+end
+
################################################################################
# Additions to `model_ext`.
import html_model
import html::bootstrap
+import doc_phases::doc_structure
+import doc_phases::doc_hierarchies
+import doc_phases::doc_graphs
+import doc_phases::doc_intros_redefs
+import doc_phases::doc_lin
# Renders the page as HTML.
redef class DocPage
var topmenu: DocTopMenu is writable, noinit
# Sidebar template if any.
- var sidebar: nullable TplSidebar = null is writable
-
- # Content of the page in form a TplSection.
- # TODO remove when other templates are migrated.
- var sections = new Array[TplSection]
+ var sidebar: nullable DocSideBar = null is writable
# Footer content if any.
var footer: nullable Writable = null is writable
# JS scripts to append at the end of the body
var scripts = new Array[TplScript]
- # Adds a section to this page.
- # TODO remove when other templates are migrated.
- fun add_section(section: TplSection) do
- sections.add section
- end
-
# Renders the html `<head>`.
private fun render_head do
var css = (self.shareurl / "css").html_escape
addn ">"
end
- # Renders the sidebar template.
- #
- # Sidebar is automatically populated with a summary of all sections
- # TODO remove summary generation when other templates are migrated.
- private fun render_sidebar do
- if sidebar == null then return
- var summary = new TplSummary.with_order(0)
- for section in sections do
- section.render_summary summary
- end
- sidebar.boxes.add summary
- add sidebar.as(not null)
- end
-
# Renders the footer and content.
private fun render_content do
- for section in sections do add section
+ add root
if footer != null then
addn "<div class='well footer'>"
add footer.as(not null)
add topmenu
addn " </div>"
addn " <div class='row' id='content'>"
+ var sidebar = self.sidebar
if sidebar != null then
addn "<div class='col col-xs-3 col-lg-2'>"
- render_sidebar
+ add sidebar
addn "</div>"
addn "<div class='col col-xs-9 col-lg-10' data-spy='scroll' data-target='.summary'>"
render_content
addn "</div>"
render_footer
end
+
+ # Render table of content for this page.
+ fun html_toc: UnorderedList do
+ var lst = new UnorderedList
+ lst.css_classes.add "nav"
+ for child in root.children do
+ child.render_toc_item(lst)
+ end
+ return lst
+ end
end
# Top menu bar template.
end
end
+# Nitdoc sidebar template.
+class DocSideBar
+ super Template
+
+ # Sidebar contains `DocSideBox`.
+ var boxes = new Array[DocSideBox]
+
+ redef fun rendering do
+ if boxes.is_empty then return
+ addn "<div id='sidebar'>"
+ for box in boxes do add box
+ addn "</div>"
+ end
+end
+
+# Something that can be put in a DocSideBar.
+class DocSideBox
+ super Template
+
+ # Box HTML id, used for Bootstrap collapsing feature.
+ #
+ # Use `html_title.to_cmangle` by default.
+ var id: String is lazy do return title.write_to_string.to_cmangle
+
+ # Title of the box to display.
+ var title: Writable
+
+ # Content to display in the box.
+ var content: Writable
+
+ # Is the box opened by default?
+ #
+ # Otherwise, the user will have to clic on the title to display the content.
+ #
+ # Default is `true`.
+ var is_open = true is writable
+
+ redef fun rendering do
+ var open = ""
+ if is_open then open = "in"
+ addn "<div class='panel'>"
+ addn " <div class='panel-heading'>"
+ add " <a data-toggle='collapse' data-parent='#sidebar'"
+ add " data-target='#box_{id}' href='#'>"
+ add title
+ addn " </a>"
+ addn " </div>"
+ addn " <div id='box_{id}' class='summary panel-body collapse {open}'>"
+ add content
+ addn " </div>"
+ addn "</div>"
+ end
+end
+
redef class DocComposite
super Template
# HTML anchor id
- var html_id: String is noinit
+ var html_id: String is noinit, writable
# Title to display if any.
#
# Render the element title and subtitle.
private fun render_title do
if html_title != null then
- addn new Header(hlvl, html_title.write_to_string)
+ var header = new Header(hlvl, html_title.write_to_string)
+ header.css_classes.add "signature"
+ if hlvl == 2 then header.css_classes.add "well well-sm"
+ addn header
end
if html_subtitle != null then
addn "<div class='info subtitle'>"
end
# Render the element body.
- private fun render_body do end
+ private fun render_body do
+ for child in children do addn child.write_to_string
+ end
redef fun rendering do
if is_hidden then return
# Level <hX> for HTML heading.
private fun hlvl: Int do
- if parent == null then return 1
+ if parent == null then return 0
return parent.hlvl + 1
end
#
# By default, empty elements are hidden.
fun is_hidden: Bool do return is_empty
+
+ # A short, undecorated title that goes in the table of contents.
+ #
+ # By default, returns `html_title.to_s`, subclasses should redefine it.
+ var toc_title: String is lazy, writable do return html_title.to_s
+
+ # Is `self` hidden in the table of content?
+ var is_toc_hidden = false is writable
+
+ # Render this element in a table of contents.
+ private fun render_toc_item(lst: UnorderedList) do
+ if is_toc_hidden then return
+
+ var content = new Template
+ content.add new Link("#{html_id}", toc_title)
+
+ if not children.is_empty then
+ var sublst = new UnorderedList
+ sublst.css_classes.add "nav"
+ for child in children do
+ child.render_toc_item(sublst)
+ end
+ content.add sublst
+ end
+ lst.add_li new ListItem(content)
+ end
end
redef class DocSection
addn "<a id=\"{html_id}\"></a>"
return
end
+ addn "<section{render_css_classes} id=\"{html_id}\">"
+ render_title
render_body
+ addn "</section>"
end
end
redef class DocArticle
super BSComponent
- # Never displays the title for article.
+ redef fun rendering do
+ if is_hidden then return
+ addn "<article{render_css_classes} id=\"{html_id}\">"
+ render_title
+ render_body
+ addn "</article>"
+ end
+end
+
+redef class HomeArticle
+ redef var html_id = "article:home"
+ redef var html_title = "Overview"
+
+ # HTML content to display on the home page.
+ #
+ # This attribute is set by the `doc_render` phase who knows the context.
+ var content: nullable String is noinit, writable
+
+ redef fun render_body do
+ var content = self.content
+ if content != null then add content
+ super
+ end
+end
+
+redef class IndexArticle
+ redef var html_id = "article:index"
+ redef var html_title = "Index"
+ redef fun is_empty do
+ return mmodules.is_empty and mclasses.is_empty and mprops.is_empty
+ end
+
+ redef fun render_body do
+ addn "<div class='container-fluid'>"
+ addn " <div class='row'>"
+ render_list("Modules", mmodules)
+ render_list("Classes", mclasses)
+ render_list("Properties", mprops)
+ addn "</div>"
+ addn "</div>"
+ end
+
+ # Displays a list from the content of `mentities`.
+ private fun render_list(title: String, mentities: Array[MEntity]) do
+ if mentities.is_empty then return
+ addn "<div class='col-xs-4'>"
+ addn new Header(3, title)
+ var lst = new UnorderedList
+ for mentity in mentities do
+ if mentity isa MProperty then
+ var tpl = new Template
+ tpl.add mentity.intro.html_link
+ tpl.add " ("
+ tpl.add mentity.intro.mclassdef.mclass.html_link
+ tpl.add ")"
+ lst.add_li new ListItem(tpl)
+ else
+ lst.add_li new ListItem(mentity.html_link)
+ end
+ end
+ addn lst
+ addn "</div>"
+ end
+end
+
+redef class ProjectsSection
+ redef var html_id = "section:projects"
+ redef var html_title = "Projects"
+end
+
+redef class MEntityComposite
+ redef var html_id is lazy do return mentity.nitdoc_id
+ redef var html_title is lazy do return mentity.nitdoc_name
+end
+
+redef class MEntitySection
+ redef var html_id is lazy do return "section:{mentity.nitdoc_name}"
+ redef var html_title is lazy do return mentity.html_name
+ redef var html_subtitle is lazy do return mentity.html_declaration
+end
+
+redef class ConcernSection
+ redef var html_id is lazy do return "concern:{mentity.nitdoc_id}"
+ redef var html_title is lazy do return "in {mentity.nitdoc_name}"
+ redef fun is_toc_hidden do return is_empty
+end
+
+redef class ImportationListSection
+ redef var html_id is lazy do return "section:{mentity.nitdoc_id}.importation"
+ redef var html_title is lazy do return "Dependencies"
+end
+
+redef class InheritanceListSection
+ redef var html_id is lazy do return "section:{mentity.nitdoc_id}.inheritance"
+ redef var html_title is lazy do return "Inheritance"
+end
+
+redef class IntroArticle
+ redef var html_id is lazy do return "article:{mentity.nitdoc_id}.intro"
+ redef var html_title = null
+ redef var is_hidden = false
+ redef var is_toc_hidden = true
+
+ # Link to source to display if any.
+ var html_source_link: nullable Writable is noinit, writable
+
+ redef fun render_title do
+ var lnk = html_source_link
+ if lnk != null then
+ add "<div class='source-link'>"
+ add lnk
+ addn "</div>"
+ end
+ super
+ end
+
+ redef fun render_body do
+ var comment = mentity.html_comment
+ if comment != null then addn comment
+ super
+ end
+end
+
+redef class ConcernsArticle
+ redef var html_id is lazy do return "article:{mentity.nitdoc_id}.concerns"
+ redef var html_title = "Concerns"
+ redef fun is_hidden do return concerns.is_empty
+ redef fun render_body do add concerns.html_list
+end
+
+redef class DefinitionArticle
+ redef var html_id is lazy do return "article:{mentity.nitdoc_id}.definition"
+ redef var html_title is lazy do return mentity.html_name
+ redef var html_subtitle is lazy do return mentity.html_declaration
+ redef var is_hidden = false
+
+ # Does `self` display only it's title and no body?
+ #
+ # FIXME diff hack
+ var is_no_body: Bool = false is writable
+
+ # Does `self` display only the short content as definition?
#
- # This is to maintain compatibility with old components, this may change
- # without notice in further version.
- redef fun render_title do end
+ # FIXME diff hack
+ var is_short_comment: Bool = false is writable
+
+ # Link to source to display if any.
+ var html_source_link: nullable Writable is noinit, writable
+
+ redef fun render_title do
+ var lnk = html_source_link
+ if lnk != null then
+ add "<div class='source-link'>"
+ add lnk
+ addn "</div>"
+ end
+ super
+ end
+
+ redef fun render_body do
+ if not is_no_body then
+ var comment
+ if is_short_comment then
+ comment = mentity.html_short_comment
+ else
+ comment = mentity.html_comment
+ end
+ if comment != null then addn comment
+ end
+ super
+ end
+end
+
+redef class HierarchyListArticle
+ redef var html_id is lazy do return "article:{list_title}_{mentity.nitdoc_id}.hierarchy"
+ redef var html_title is lazy do return list_title
+ redef fun is_empty do return mentities.is_empty
+ redef fun is_toc_hidden do return mentities.is_empty
+
+ redef fun render_body do
+ var lst = new UnorderedList
+ lst.css_classes.add "list-unstyled list-definition"
+ for mentity in mentities do
+ lst.add_li mentity.html_list_item
+ end
+ addn lst
+ end
+end
+
+redef class IntrosRedefsListArticle
+ redef var html_id is lazy do return "article:{mentity.nitdoc_id}.intros_redefs"
+ redef var html_title is lazy do return list_title
+ redef fun is_hidden do return mentities.is_empty
+ redef var is_toc_hidden = true
+
+ redef fun render_body do
+ var lst = new UnorderedList
+ lst.css_classes.add "list-unstyled list-labeled"
+ for mentity in mentities do
+ lst.add_li mentity.html_list_item
+ end
+ add lst
+ end
+end
+
+redef class DefinitionLinArticle
+ redef var html_id is lazy do return "article:{mentity.nitdoc_id}.lin"
+ redef var html_title is lazy do return "Linearization"
+ redef fun is_hidden do return mentities.is_empty
+ redef var is_toc_hidden = true
+
+ redef fun render_body do
+ var lst = new UnorderedList
+ lst.css_classes.add "list-unstyled list-labeled"
+ for mentity in mentities do
+ if not mentity isa MPropDef then continue # TODO handle all mentities
+ var tpl = new Template
+ tpl.add mentity.mclassdef.html_namespace
+ var comment = mentity.mclassdef.html_short_comment
+ if comment != null then
+ tpl.add ": "
+ tpl.add comment
+ end
+ var li = new ListItem(tpl)
+ li.css_classes.add "signature"
+ lst.add_li li
+ end
+ add lst
+ end
+end
+
+redef class GraphArticle
+ redef var html_id is lazy do return "article:{mentity.nitdoc_id}.graph"
+ redef var html_title = null
+ redef var toc_title do return "Graph"
+ redef var is_hidden = false
+ redef var is_toc_hidden = true
+
+ # HTML map used to display link.
+ #
+ # This attribute is set by the `doc_render` phase who knows the context.
+ var map: String is noinit, writable
+
+ redef fun render_body do
+ addn "<div class=\"text-center\">"
+ addn " <img src='{id}.png' usemap='#{id}' style='margin:auto'"
+ addn " alt='{graph_title}'/>"
+ add map
+ addn "</div>"
+ end
end
import check_annotation
import glsl_validation
import parallelization_phase
+import i18n_phase
redef class ToolContext
# FIXME: there is conflict in linex in nitc, so use this trick to force invocation
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+# Basic support of internationalization through the generation of id-to-string tables
+module i18n_phase
+
+intrude import literal
+private import annotation
+private import parser_util
+import astbuilder
+
+redef class ToolContext
+ # Main phase of `language`
+ var localize_phase: Phase = new I18NPhase(self, [literal_phase])
+end
+
+private class I18NPhase
+ super Phase
+
+ redef fun process_annotated_node(nmodule, nat) do
+ if not nat.name == "i18n" then return
+
+ if not nmodule isa AModuledecl then
+ toolcontext.error(nmodule.location, "Error: The localized language can only be used on module declarations.")
+ return
+ end
+
+ var domain = nmodule.n_name.n_id.text
+
+ var lang: nullable String = null
+ if nat.n_args.length > 0 then
+ lang = nat.arg_as_string(toolcontext.modelbuilder)
+ if lang == null then return
+ end
+
+ var module_dir = nmodule.location.file.filename.dirname.realpath
+ var locale_dir = module_dir / "languages"
+
+ if not locale_dir.file_exists then locale_dir.mkdir
+
+ var amodule = nmodule.parent.as(AModule)
+
+ var vi = new StringFinder(domain, locale_dir, toolcontext, amodule)
+ vi.enter_visit(amodule)
+
+ var module_name = nmodule.location.file.filename.basename(".nit")
+
+ var pot_path = locale_dir / module_name
+ var arr = vi.strings.values.to_a
+ var po = new POFile.with_strings(arr)
+ po.write_template(pot_path)
+
+ if lang != null then
+ for i in po.strings do
+ i.msgstr = i.msgid
+ end
+
+ var lang_dir = locale_dir / lang
+ if not lang_dir.file_exists then lang_dir.mkdir
+
+ var messages_dir = lang_dir / "LC_MESSAGES"
+ if not messages_dir.file_exists then messages_dir.mkdir
+
+ po.write_to_file(messages_dir / module_name)
+ end
+
+ var lit = new LiteralVisitor(toolcontext)
+ lit.enter_visit(amodule)
+ end
+end
+
+private class StringFinder
+ super Visitor
+
+ # Strings in the file, used to generate .pot and .po files
+ var strings = new HashMap[String, PObject]
+
+ # Domain of the strings to internationalize
+ var domain: String
+
+ # Location of the languages file
+ var languages_location: String
+
+ # Context for the visitor, used only for the parse_expr
+ var toolcontext: ToolContext
+
+ # The module we are working on
+ var amodule: AModule
+
+ redef fun visit(n)
+ do
+ n.accept_string_finder(self)
+ n.visit_all(self)
+ end
+
+ redef fun enter_visit(e) do
+ if e isa AAnnotation then return
+ super
+ end
+end
+
+redef class ANode
+ private fun accept_string_finder(v: StringFinder) do end
+end
+
+redef class AStringExpr
+
+ redef fun accept_string_finder(v) do
+ var str = value.as(not null).escape_to_c
+ var parse = v.toolcontext.parse_expr("\"{str}\".get_translation(\"{v.domain}\", \"{v.languages_location}\").unescape_nit")
+ var loc = location
+ var locstr = "{v.amodule.mmodule.mgroup.name}::{v.amodule.mmodule.name} {loc.line_start}--{loc.column_start}:{loc.column_end}"
+ if not v.strings.has_key(str) then
+ var po = new PObject([locstr], str, "")
+ v.strings[str] = po
+ else
+ v.strings[str].locations.push locstr
+ end
+ replace_with(parse)
+ end
+end
+
+# .po file entry
+#
+# Locations are optional, they just serve for translation purposes
+# to help the translator with the context of the message if necessary
+#
+# msgid and msgstr are the map of translate to translated strings in the po file.
+class PObject
+ # Array since the same string can be encountered at several places
+ var locations: Array[String]
+ # Identifier of the string to translate (i.e. the string itself)
+ var msgid: String is writable
+ # Translation of the string
+ var msgstr: String is writable
+end
+
+# A GNU gettext .po/.pot file
+class POFile
+ super Writable
+
+ # Map of the strings's `msgid` and `msgstr`
+ #
+ # Read from a PO file
+ var strings: Array[PObject]
+
+ # Creates a PO file with strings built-in
+ init with_strings(sm: Array[PObject])do
+ strings = new Array[PObject].with_capacity(sm.length)
+ strings.add_all sm
+ end
+
+ redef fun write_to_file(path) do
+ if not path.has_suffix(".po") then path += ".po"
+ super path
+ end
+
+ redef fun write_to(ofs) do
+ for i in strings do
+ ofs.write("#: {i.locations.join(", ")}\n")
+ ofs.write("msgid \"{i.msgid}\"\n")
+ ofs.write("msgstr \"{i.msgstr}\"\n\n")
+ end
+ ofs.write("# Generated file, do not modify\n")
+ end
+
+ # Writes the information of the POFile to a .pot template file
+ fun write_template(path: String) do
+ if not path.has_suffix(".pot") then path += ".pot"
+ var f = new FileWriter.open(path)
+ write_to(f)
+ f.close
+ end
+end
new StructurePhase(toolcontext, doc),
new InheritanceListsPhase(toolcontext, doc),
new IntroRedefListPhase(toolcontext, doc),
+ new LinListPhase(toolcontext, doc),
new GraphPhase(toolcontext, doc),
new RenderHTMLPhase(toolcontext, doc): DocPhase]
var opt_meld = new OptionBool("Show diff between source and output using meld",
"--meld")
+ # --line-width
+ var opt_line_width = new OptionInt("Maximum length of lines (use 0 to disable automatic line breaks)", 80, "--line-width")
+
+ # --no-inline
+ var opt_no_inline = new OptionBool("Disable automatic one-liners", "--no-inline")
+
# Break too long string literals.
var opt_break_str = new OptionBool("Break too long string literals", "--break-strings")
var opts = toolcontext.option_context
opts.add_option(toolcontext.opt_dir, toolcontext.opt_output)
opts.add_option(toolcontext.opt_diff, toolcontext.opt_meld, toolcontext.opt_check)
-opts.add_option(toolcontext.opt_break_str, toolcontext.opt_inline_do)
+opts.add_option(toolcontext.opt_line_width, toolcontext.opt_break_str, toolcontext.opt_inline_do)
+opts.add_option(toolcontext.opt_no_inline)
opts.add_option(toolcontext.opt_skip_empty)
toolcontext.tooldescription = "Usage: nitpretty [OPTION]... <file.nit>\n" +
# build model
var model = new Model
var mbuilder = new ModelBuilder(model, toolcontext)
-var mmodules = mbuilder.parse(arguments)
+var mmodules = mbuilder.parse_full(arguments)
mbuilder.run_phases
if mmodules.is_empty then
if not dir.file_exists then dir.mkdir
var v = new PrettyPrinterVisitor
+v.max_size = toolcontext.opt_line_width.value
if toolcontext.opt_break_str.value then
v.break_strings = true
end
if toolcontext.opt_skip_empty.value then
v.skip_empty = true
end
+if toolcontext.opt_no_inline.value then
+ v.no_inline = true
+end
for mmodule in mmodules do
var nmodule = mbuilder.mmodule2node(mmodule)
android:label="@string/app_name"
android:hasCode="true"
android:debuggable="{{{not release}}}"
- {{{icon_declaration}}}
- android:configChanges="mcc|mnc|locale|touchscreen|keyboard|keyboardHidden|navigation|screenLayout|fontScale|uiMode|orientation">
+ {{{icon_declaration}}}>
"""
for activity in project.activities do
n.accept_pretty_printer self
end
- # Visit a list of `Anode`.
+ # Visit a list of arguments `ANode` with optional parentheses
+ fun visit_args(n: nullable ANodes[ANode]) do
+ if n == null or n.is_empty then return
+ if current_token isa TOpar then
+ consume "("
+ else
+ adds
+ end
+
+ visit_list n
+ if current_token isa TCpar then consume ")"
+ end
+
+ # Visit a list of `ANode`.
fun visit_list(n: nullable ANodes[ANode]) do
if n == null then return
n.accept_pretty_printer self
# Is the node inlinable and can fit on the line.
fun can_inline(n: nullable ANode): Bool do
if n == null then return true
+ if no_inline and n.location.line_start != n.location.line_end then return false
if n.must_be_inline then return true
if n.must_be_block then return false
# check length
- if n.collect_length + current_length > max_size then return false
+ if max_size > 0 and n.collect_length + current_length > max_size then return false
# check block is inlinable
return n.is_inlinable
end
# Skip `current_token` until `target` is reached.
fun skip_to(target: nullable Token) do
if target == null then return
- while current_token != target do skip
+ while current_token != null and current_token != target do skip
+ if current_token == null then
+ target.debug("Looked for, but not found :(")
+ abort
+ end
+ end
+
+ # Consume comments and end of lines if any
+ fun consume_comments do
+ while current_token isa TEol or current_token isa TComment do visit current_token
end
# Visit `current_token`.
fun consume(token: String) do
- assert current_token.text == token
+ consume_comments
+ if current_token.text == token then else current_token.debug("Got `{current_token.text}`; expected `{token}`.")
visit current_token
end
var tab_size = 8
# Max line size.
- var max_size = 80
+ # 0 (or negative) to disable.
+ var max_size = 80 is writable
# Length of the current line.
var current_length = 0
# Do we force the deletion of empty lines?
var skip_empty = false is public writable
+
+ # Disable automatic inlining.
+ var no_inline = false is writable
end
# Base framework redefs
for e in self do
var e_can_inline = v.can_inline(e)
+ if v.current_token isa TComma then v.skip
+
if e != first then
if not e_can_inline then
v.add ","
v.adds
end
v.visit n_atid
- if not n_args.is_empty then
- if n_opar == null then
- v.adds
- else
- v.visit n_opar
- end
- v.visit_list n_args
- v.visit n_cpar
- end
+ v.visit_args n_args
end
end
v.adds
v.visit_list n_extern_calls
else
- v.addn
+ v.forcen
v.indent += 1
v.addt
v.indent -= 1
v.add "`\{"
if not lines.first.trim.is_empty then
- v.addn
+ v.forcen
lines.first.l_trim
v.indent += 1
v.addt
v.adds
else
v.visit n_expr
- v.addn
+ v.forcen
v.addt
end
end
end
- if has_else(v) then
- while not v.current_token isa TKwelse do
- v.consume v.current_token.text
- end
+ v.consume_comments
+
+ # FIXME: for some unknown reasons, has_else can be true even if
+ # there is no `else` keyword but a `end` instead.
+ if has_else(v) and v.current_token isa TKwelse then
v.indent -= 1
v.addt
v.visit_recv n_expr
if not n_expr isa AImplicitSelfExpr and not can_inline then
- v.addn
+ v.forcen
v.addt
end
v.visit n_args.n_exprs.first
if v.current_token isa TCpar then v.skip
else
- if v.current_token isa TOpar then
- v.consume "("
- else
- v.adds
- end
-
- v.visit_list n_args.n_exprs
- if v.current_token isa TCpar then v.consume ")"
+ v.visit_args n_args.n_exprs
end
end
end
end
v.visit n_kwinit
-
- if not n_args.n_exprs.is_empty then
- v.consume "("
- v.visit_list n_args.n_exprs
- v.consume ")"
- end
+ v.visit_args n_args.n_exprs
end
end
v.consume "."
if not can_inline then
- v.addn
+ v.forcen
v.indent += 1
v.addt
v.indent -= 1
v.visit n_id
end
- if not n_args.n_exprs.is_empty then
- v.consume "("
- v.visit_list n_args.n_exprs
- v.consume ")"
- end
+ v.visit_args n_args.n_exprs
end
redef fun is_inlinable do return true
else
v.addt
v.visit n_else
- v.addn
+ v.forcen
v.indent -= 1
v.addt
v.add "end"
v.visit n_args.n_exprs.first
if v.current_token isa TCpar then v.skip
else
- if v.current_token isa TOpar then
- v.consume "("
- else
- v.adds
- end
-
- v.visit_list n_args.n_exprs
- if v.current_token isa TCpar then v.consume ")"
+ v.visit_args n_args.n_exprs
end
end
end
v.adds
v.visit bin_expr2
else
- v.addn
+ v.forcen
v.indent += 1
v.addt
v.indent -= 1
redef fun accept_pretty_printer(v) do
v.consume "["
v.visit_list n_exprs
+ if n_type != null then
+ v.consume ":"
+ v.adds
+ v.visit n_type
+ end
v.consume "]"
end
end
while i < text.length do
v.add text[i].to_s
- if v.current_length >= v.max_size and i <= text.length - 3 then
+ if v.max_size > 0 and v.current_length >= v.max_size and i <= text.length - 3 then
v.add "\" +"
if was_inline then
v.forcen
var transform_phase: Phase = new TransformPhase(self, [typing_phase, auto_super_init_phase])
# --no-shortcut-range
- var opt_no_shortcut_range: OptionBool = new OptionBool("Always insantiate a range and its iterator on 'for' loops", "--no-shortcut-range")
+ var opt_no_shortcut_range: OptionBool = new OptionBool("Always instantiate a range and its iterator on 'for' loops", "--no-shortcut-range")
redef init
do
websocket_server
converter
show_basedir
+langannot
--- /dev/null
+][[]][ is not well-balanced
+[[]][] is well-balanced
+[]][][ is not well-balanced
+[[[]]] is well-balanced
+[][]][ is not well-balanced
+]][[][ is not well-balanced
+[]]][[ is not well-balanced
+[]][][ is not well-balanced
+[][][] is well-balanced
+][]][[ is not well-balanced
--- /dev/null
+Read 4 chars: # Th
+Read 4 chars: is f
+Read 4 chars: ile
+Read 4 chars: is p
+Read 4 chars: art
+Read 4 chars: of N
+Read 4 chars: IT (
+Read 4 chars: htt
+Read 4 chars: p://
+Read 4 chars: www.
+Read 4 chars: nitl
+Read 4 chars: angu
+Read 4 chars: age.
+Read 4 chars: org
+Read 4 chars: ).
+#
+Read 4 chars:
+# C
+Read 4 chars: opyr
+Read 4 chars: ight
+Read 4 chars: 201
+Read 4 chars: 3 Al
+Read 4 chars: exis
+Read 4 chars: Laf
+Read 4 chars: erri
+Read 4 chars: ère
+Read 4 chars: <al
+Read 4 chars: exis
+Read 4 chars: .laf
+Read 4 chars: @xym
+Read 4 chars: us.n
+Read 4 chars: et>
+
+Read 4 chars: #
+#
+Read 4 chars: Lice
+Read 4 chars: nsed
+Read 4 chars: und
+Read 4 chars: er t
+Read 4 chars: he A
+Read 4 chars: pach
+Read 4 chars: e Li
+Read 4 chars: cens
+Read 4 chars: e, V
+Read 4 chars: ersi
+Read 4 chars: on 2
+Read 4 chars: .0 (
+Read 4 chars: the
+Read 4 chars: "Lic
+Read 4 chars: ense
+Read 4 chars: ");
+
+Read 4 chars: # yo
+Read 4 chars: u ma
+Read 4 chars: y no
+Read 4 chars: t us
+Read 4 chars: e th
+Read 4 chars: is f
+Read 4 chars: ile
+Read 4 chars: exce
+Read 4 chars: pt i
+Read 4 chars: n co
+Read 4 chars: mpli
+Read 4 chars: ance
+Read 4 chars: wit
+Read 4 chars: h th
+Read 4 chars: e Li
+Read 4 chars: cens
+Read 4 chars: e.
+#
+Read 4 chars: You
+Read 4 chars: may
+Read 4 chars: obt
+Read 4 chars: ain
+Read 4 chars: a co
+Read 4 chars: py o
+Read 4 chars: f th
+Read 4 chars: e Li
+Read 4 chars: cens
+Read 4 chars: e at
+Read 4 chars:
+#
+#
+Read 4 chars:
+Read 4 chars: htt
+Read 4 chars: p://
+Read 4 chars: www.
+Read 4 chars: apac
+Read 4 chars: he.o
+Read 4 chars: rg/l
+Read 4 chars: icen
+Read 4 chars: ses/
+Read 4 chars: LICE
+Read 4 chars: NSE-
+Read 4 chars: 2.0
+
+Read 4 chars: #
+#
+Read 4 chars: Unle
+Read 4 chars: ss r
+Read 4 chars: equi
+Read 4 chars: red
+Read 4 chars: by a
+Read 4 chars: ppli
+Read 4 chars: cabl
+Read 4 chars: e la
+Read 4 chars: w or
+Read 4 chars: agr
+Read 4 chars: eed
+Read 4 chars: to i
+Read 4 chars: n wr
+Read 4 chars: itin
+Read 4 chars: g, s
+Read 4 chars: oftw
+Read 4 chars: are
+
+Read 4 chars: # di
+Read 4 chars: stri
+Read 4 chars: bute
+Read 4 chars: d un
+Read 4 chars: der
+Read 4 chars: the
+Read 4 chars: Lice
+Read 4 chars: nse
+Read 4 chars: is d
+Read 4 chars: istr
+Read 4 chars: ibut
+Read 4 chars: ed o
+Read 4 chars: n an
+Read 4 chars: "AS
+Read 4 chars: IS"
+Read 4 chars: BAS
+Read 4 chars: IS,
+
+Read 4 chars: # WI
+Read 4 chars: THOU
+Read 4 chars: T WA
+Read 4 chars: RRAN
+Read 4 chars: TIES
+Read 4 chars: OR
+Read 4 chars: COND
+Read 4 chars: ITIO
+Read 4 chars: NS O
+Read 4 chars: F AN
+Read 4 chars: Y KI
+Read 4 chars: ND,
+Read 4 chars: eith
+Read 4 chars: er e
+Read 4 chars: xpre
+Read 4 chars: ss o
+Read 4 chars: r im
+Read 4 chars: plie
+Read 4 chars: d.
+#
+Read 4 chars: See
+Read 4 chars: the
+Read 4 chars: Lic
+Read 4 chars: ense
+Read 4 chars: for
+Read 4 chars: the
+Read 4 chars: spe
+Read 4 chars: cifi
+Read 4 chars: c la
+Read 4 chars: ngua
+Read 4 chars: ge g
+Read 4 chars: over
+Read 4 chars: ning
+Read 4 chars: per
+Read 4 chars: miss
+Read 4 chars: ions
+Read 4 chars: and
+Read 4 chars:
+# l
+Read 4 chars: imit
+Read 4 chars: atio
+Read 4 chars: ns u
+Read 4 chars: nder
+Read 4 chars: the
+Read 4 chars: Lic
+Read 4 chars: ense
+Read 4 chars: .
+
+m
+Read 4 chars: odul
+Read 4 chars: e te
+Read 4 chars: st_a
+Read 4 chars: nnot
+Read 4 chars: _c_c
+Read 4 chars: ompi
+Read 4 chars: ler
+Read 4 chars: is
+
+Read 4 chars: cfla
+Read 4 chars: gs "
+Read 4 chars: -I /
+Read 4 chars: usr/
+Read 4 chars: incl
+Read 4 chars: ude"
+Read 4 chars:
+ cf
+Read 4 chars: lags
+Read 4 chars: exe
+Read 4 chars: c("p
+Read 4 chars: kg-c
+Read 4 chars: onfi
+Read 4 chars: g",
+Read 4 chars: "--c
+Read 4 chars: flag
+Read 4 chars: s",
+Read 4 chars: "sdl
+Read 4 chars: ")
+
+Read 4 chars: ldfl
+Read 4 chars: ags
+Read 4 chars: "-lm
+Read 4 chars: "
+ l
+Read 4 chars: dfla
+Read 4 chars: gs("
+Read 4 chars: -lm"
+Read 4 chars: , "-
+Read 4 chars: L /u
+Read 4 chars: sr/b
+Read 4 chars: in")
+Read 4 chars:
+end
+Read 4 chars:
+
+fu
+Read 4 chars: n du
+Read 4 chars: mmy
+Read 4 chars: `{ p
+Read 4 chars: rint
+Read 4 chars: f("n
+Read 4 chars: othi
+Read 4 chars: ng..
+Read 4 chars: .\n"
+Read 4 chars: ); `
+Read 4 chars: }
+
+d
+Read 4 chars: ummy
+Read 1 chars:
+
--- /dev/null
+# This file is part of NIT ( http://www.nitlanguage.org ).
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+var f = new FileReader.open("test_annot_c_compiler.nit")
+
+while not f.eof do
+ var s = f.read(4)
+ print "Read {s.length} chars: {s}"
+end
+
+f.close
export LANG=C
export LC_ALL=C
export NIT_TESTING=true
-export MNIT_SRAND=0
+export NIT_SRAND=0
unset NIT_DIR