nitx: nitx use doc commands
authorAlexandre Terrasa <alexandre@moz-code.org>
Thu, 26 Oct 2017 00:01:31 +0000 (20:01 -0400)
committerAlexandre Terrasa <alexandre@moz-code.org>
Fri, 8 Dec 2017 20:10:38 +0000 (15:10 -0500)
Signed-off-by: Alexandre Terrasa <alexandre@moz-code.org>

src/doc/console_templates/console_model.nit [deleted file]
src/doc/console_templates/console_templates.nit [deleted file]
src/doc/doc_phases/doc_console.nit [deleted file]
src/doc/templates/templates_term.nit [new file with mode: 0644]
src/doc/term/term.nit [new file with mode: 0644]
src/nitx.nit

diff --git a/src/doc/console_templates/console_model.nit b/src/doc/console_templates/console_model.nit
deleted file mode 100644 (file)
index cacac49..0000000
+++ /dev/null
@@ -1,668 +0,0 @@
-# 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.
-
-# Console templates for Nit model MEntities.
-#
-# This module introduces console rendering services in model entities.
-module console_model
-
-import console
-import doc_base
-import ordered_tree
-
-redef class MDoc
-       # Returns the full comment formatted for the console.
-       fun cs_comment: String do
-               var res = new FlatBuffer
-               for line in content do
-                       res.append "    {line}\n"
-               end
-               return res.write_to_string
-       end
-
-       # Returns the synopsys formatted for the console.
-       fun cs_short_comment: String do return content.first
-end
-
-redef class MEntity
-
-       # Returns the mentity name with short signature.
-       #
-       # * MPackage: `foo`
-       # * MGroup: `foo`
-       # * MModule: `foo`
-       # * MClass: `Foo[E]`
-       # * MClassDef: `Foo[E]`
-       # * MProperty: `foo(e)`
-       # * MPropdef: `foo(e)`
-       var cs_name: String is lazy do return name
-
-       # Returns the list of keyword used in `self` declaration.
-       fun cs_modifiers: Array[String] is abstract
-
-       # Returns the complete MEntity declaration (modifiers + name + signature).
-       #
-       # * MPackage: `package foo`
-       # * MGroup: `group foo`
-       # * MModule: `module foo`
-       # * MClass: `private abstract class Foo[E: Object]`
-       # * MClassDef: `redef class Foo[E]`
-       # * MProperty: `private fun foo(e: Object): Int`
-       # * MPropdef: `redef fun foo(e)`
-       var cs_declaration: String is lazy do
-               var tpl = new FlatBuffer
-               tpl.append cs_modifiers.join(" ")
-               tpl.append " "
-               tpl.append cs_name
-               return tpl.write_to_string
-       end
-
-       # Returns `self` namespace formatted for console.
-       #
-       # * MPackage: `mpackage`
-       # * MGroup: `mpackage(::group)`
-       # * MModule: `mgroup::mmodule`
-       # * MClass: `mpackage::mclass`
-       # * MClassDef: `mmodule::mclassdef`
-       # * MProperty: `mclass::mprop`
-       # * MPropdef: `mclassdef:mpropdef`
-       fun cs_namespace: String is abstract
-
-       # Returns the comment of this MEntity formatted for console.
-       var cs_comment: nullable String is lazy do
-               var mdoc = mdoc_or_fallback
-               if mdoc == null then return null
-               # FIXME add markdown for console
-               return mdoc.cs_comment
-       end
-
-       # Returns the comment of this MEntity formatted for console.
-       var cs_short_comment: nullable String is lazy do
-               var mdoc = mdoc_or_fallback
-               if mdoc == null then return null
-               return mdoc.cs_short_comment
-       end
-
-       # Returns `self` as a list element that can be displayed in console.
-       #
-       # Displays `cs_icon`, `cs_name`, `cs_short_comment, `cs_namespace`,
-       # `cs_declaration` and `cs_location`.
-       fun cs_list_item: String do
-               var tpl = new FlatBuffer
-               tpl.append " {cs_visibility_color(cs_icon).bold} {cs_name.blue.bold}"
-               var comment = cs_short_comment
-               if comment != null then
-                       tpl.append " # {comment}".green
-               end
-               tpl.append "\n   "
-               tpl.append cs_namespace.gray.bold
-               tpl.append "\n   "
-               tpl.append cs_declaration
-               tpl.append "\n   "
-               tpl.append cs_location.gray
-               return tpl.write_to_string
-       end
-
-       # Returns `self` as a short list element that can be displayed in console.
-       # Displays `cs_icon`, `cs_name`, and `cs_short_comment.
-       fun cs_short_list_item: String do
-               var tpl = new FlatBuffer
-               tpl.append " {cs_visibility_color(cs_icon).bold} {cs_name.blue.bold}"
-               var comment = cs_short_comment
-               if comment != null then
-                       tpl.append " # {comment}".green
-               end
-               return tpl.write_to_string
-       end
-
-       # ASCII icon to be displayed in front of the list item.
-       fun cs_icon: String do return "*"
-
-       # Source code location of this MEntity formatted for console.
-       fun cs_location: String is abstract
-
-       # Sets text color depending on visibility.
-       #
-       # See module `console`.
-       fun cs_visibility_color(string: String): String do return string.green
-
-       # Source code associated to this MEntity.
-       #
-       # Uses `cs_location` to locate the source code.
-       fun cs_source_code: String do
-               # FIXME up location to mentity
-               var loc = new Location.from_string(cs_location)
-               var fr = new FileReader.open(loc.file.filename)
-               var content = new FlatBuffer
-               var i = 0
-               while not fr.eof do
-                       i += 1
-                       var line = fr.read_line
-                       if i < loc.line_start or i > loc.line_end then continue
-                       # FIXME add nitlight for console
-                       content.append "{line}\n"
-               end
-               fr.close
-               return content.write_to_string
-       end
-end
-
-redef class MPackage
-       redef var cs_modifiers = ["package"]
-       redef fun cs_namespace do return cs_name
-       redef fun cs_icon do return "P"
-       redef fun cs_location do return root.mmodules.first.location.to_s
-end
-
-redef class MGroup
-       redef var cs_modifiers = ["group"]
-       redef fun cs_icon do return "G"
-
-       # Depends if `self` is root or not.
-       #
-       # * If root `mpackage`.
-       # * Else `mpackage::self`.
-       redef fun cs_namespace do
-               var tpl = new FlatBuffer
-               tpl.append mpackage.cs_namespace
-               if mpackage.root != self then
-                       tpl.append "::"
-                       tpl.append cs_name
-               end
-               return tpl.write_to_string
-       end
-
-       redef fun cs_location do return mmodules.first.location.to_s
-end
-
-redef class MModule
-       redef var cs_modifiers = ["module"]
-       redef fun cs_icon do return "M"
-
-       # Depends if `self` belongs to a MGroup.
-       #
-       # * If mgroup `mgroup::self`.
-       # * Else `self`.
-       redef fun cs_namespace do
-               var tpl = new FlatBuffer
-               if mgroup != null then
-                       tpl.append mgroup.cs_namespace
-                       tpl.append "::"
-               end
-               tpl.append cs_name
-               return tpl.write_to_string
-       end
-
-       redef fun cs_location do return location.to_s
-end
-
-redef class MClass
-       redef fun cs_icon do return intro.cs_icon
-
-       # Format: `Foo[E]`
-       redef var cs_name is lazy do
-               var tpl = new FlatBuffer
-               tpl.append name
-               if arity > 0 then
-                       tpl.append "["
-                       var parameter_names = new Array[String]
-                       for p in mparameters do
-                               parameter_names.add(p.cs_name)
-                       end
-                       tpl.append parameter_names.join(", ")
-                       tpl.append "]"
-               end
-               return tpl.write_to_string
-       end
-
-       redef fun cs_modifiers do return intro.cs_modifiers
-       redef fun cs_declaration do return intro.cs_declaration
-
-       # Returns `mpackage::self`.
-       redef fun cs_namespace do
-               var tpl = new FlatBuffer
-               tpl.append intro_mmodule.mgroup.mpackage.cs_namespace
-               tpl.append "::"
-               tpl.append cs_name
-               return tpl.write_to_string
-       end
-
-       # Returns `intro.cs_short_signature`.
-       fun cs_short_signature: String do return intro.cs_short_signature
-
-       # Returns `intro.cs_signature`.
-       fun cs_signature: String do return intro.cs_signature
-
-       redef fun cs_visibility_color(string) do
-               if visibility == private_visibility then
-                       return string.red
-               else if visibility == protected_visibility then
-                       return string.yellow
-               end
-               return string.green
-       end
-
-       redef fun cs_location do return intro.location.to_s
-end
-
-redef class MClassDef
-       redef fun cs_icon do return "C"
-
-       # Depends if `self` is an intro or not.
-       #
-       # * If intro contains the visibility and kind.
-       # * If redef contains the `redef` keyword and kind.
-       redef fun cs_modifiers do
-               var res = new Array[String]
-               if not is_intro then
-                       res.add "redef"
-               else
-                       if mclass.visibility != public_visibility then
-                               res.add mclass.visibility.to_s
-                       end
-               end
-               res.add mclass.kind.to_s
-               return res
-       end
-
-       # Depends if `self` is an intro or not.
-       #
-       # For intro: `private abstract class Foo[E: Object]`
-       # For redef: `redef class Foo[E]`
-       redef fun cs_declaration do
-               var tpl = new FlatBuffer
-               tpl.append cs_modifiers.join(" ")
-               tpl.append " "
-               tpl.append cs_name
-               if is_intro then
-                       tpl.append cs_signature
-               else
-                       tpl.append cs_short_signature
-               end
-               return tpl.write_to_string.write_to_string.write_to_string
-       end
-
-       # Returns `mmodule::self`
-       redef fun cs_namespace do
-               var tpl = new FlatBuffer
-               tpl.append mmodule.cs_namespace
-               tpl.append "::"
-               tpl.append mclass.cs_name
-               return tpl.write_to_string.write_to_string
-       end
-
-       # Returns the MClassDef generic signature without static bounds.
-       fun cs_short_signature: String do
-               var tpl = new FlatBuffer
-               var mparameters = mclass.mparameters
-               if not mparameters.is_empty then
-                       tpl.append "["
-                       for i in [0..mparameters.length[ do
-                               tpl.append mparameters[i].cs_name
-                               if i < mparameters.length - 1 then tpl.append ", "
-                       end
-                       tpl.append "]"
-               end
-               return tpl.write_to_string
-       end
-
-       # Returns the MClassDef generic signature with static bounds.
-       fun cs_signature: String do
-               var tpl = new FlatBuffer
-               var mparameters = mclass.mparameters
-               if not mparameters.is_empty then
-                       tpl.append "["
-                       for i in [0..mparameters.length[ do
-                               tpl.append "{mparameters[i].cs_name}: "
-                               tpl.append bound_mtype.arguments[i].cs_signature
-                               if i < mparameters.length - 1 then tpl.append ", "
-                       end
-                       tpl.append "]"
-               end
-               return tpl.write_to_string
-       end
-
-       redef fun cs_location do return location.to_s
-end
-
-redef class MProperty
-       redef fun cs_modifiers do return intro.cs_modifiers
-       redef fun cs_declaration do return intro.cs_declaration
-       redef fun cs_icon do return intro.cs_icon
-
-       # Returns `mclass::self`.
-       redef fun cs_namespace do
-               var tpl = new FlatBuffer
-               tpl.append intro_mclassdef.mclass.cs_namespace
-               tpl.append "::"
-               tpl.append intro.cs_name
-               return tpl.write_to_string
-       end
-
-       # Returns `intro.cs_short_signature`.
-       fun cs_short_signature: String do return intro.cs_short_signature
-
-       # Returns `intro.cs_signature`.
-       fun cs_signature: String do return intro.cs_signature
-
-       redef fun cs_visibility_color(string) do
-               if visibility == private_visibility then
-                       return string.red
-               else if visibility == protected_visibility then
-                       return string.yellow
-               end
-               return string.green
-       end
-
-       # Returns `intro.cs_location`.
-       redef fun cs_location do return intro.location.to_s
-end
-
-redef class MPropDef
-       # Depends if `self` is an intro or not.
-       #
-       # * If intro contains the visibility and kind.
-       # * If redef contains the `redef` keyword and kind.
-       redef fun cs_modifiers do
-               var res = new Array[String]
-               if not is_intro then
-                       res.add "redef"
-               else
-                       if mproperty.visibility != public_visibility then
-                               res.add mproperty.visibility.to_s
-                       end
-               end
-               return res
-       end
-
-       # Depends if `self` is an intro or not.
-       #
-       # For intro: `private fun foo(e: Object): Bar is abstract`
-       # For redef: `redef fun foo(e) is cached`
-       redef fun cs_declaration do
-               var tpl = new FlatBuffer
-               tpl.append cs_modifiers.join(" ")
-               tpl.append " "
-               if is_intro then
-                       tpl.append cs_name
-                       tpl.append cs_signature
-               else
-                       tpl.append mproperty.intro.cs_name
-                       tpl.append cs_short_signature
-               end
-               return tpl.write_to_string
-       end
-
-       # Returns `mclassdef::self`
-       redef fun cs_namespace do
-               var tpl = new FlatBuffer
-               tpl.append mclassdef.cs_namespace
-               tpl.append "::"
-               tpl.append cs_name
-               return tpl.write_to_string
-       end
-
-       redef fun cs_location do return location.to_s
-
-       # Returns the MPropdDef signature without static types.
-       fun cs_short_signature: String is abstract
-
-       # Returns the MPropDef signature with static types.
-       fun cs_signature: String is abstract
-end
-
-redef class MAttributeDef
-
-       redef fun cs_modifiers do
-               var res = super
-               res.add "var"
-               return res
-       end
-
-       redef fun cs_short_signature do return ""
-
-       redef fun cs_signature do
-               var tpl = new FlatBuffer
-               if static_mtype != null then
-                       tpl.append ": "
-                       tpl.append static_mtype.cs_signature
-               end
-               return tpl.write_to_string
-       end
-
-       redef fun cs_icon do return "A"
-end
-
-redef class MMethodDef
-
-       redef fun cs_modifiers do
-               if mproperty.is_init then
-                       var res = new Array[String]
-                       if mproperty.visibility != public_visibility then
-                               res.add mproperty.visibility.to_s
-                       end
-                       return res
-               end
-               var res = super
-               if is_abstract then
-                       res.add "abstract"
-               else if is_intern then
-                       res.add "intern"
-               end
-               res.add "fun"
-               return res
-       end
-
-       redef fun cs_declaration do
-               if mproperty.is_init then
-                       var tpl = new FlatBuffer
-                       if not cs_modifiers.is_empty then
-                               tpl.append cs_modifiers.join(" ")
-                               tpl.append " "
-                       end
-                       tpl.append cs_name
-                       tpl.append cs_signature
-                       return tpl.write_to_string
-               end
-               return super
-       end
-
-       redef fun cs_short_signature do
-               if mproperty.is_root_init then
-                       return new_msignature.cs_short_signature
-               end
-               return msignature.cs_short_signature
-       end
-
-       redef fun cs_signature do
-               if mproperty.is_root_init then
-                       return new_msignature.cs_signature
-               end
-               return msignature.cs_signature
-       end
-
-       redef fun cs_icon do
-               if mproperty.is_init then
-                       return "I"
-               end
-               return "F"
-       end
-end
-
-redef class MVirtualTypeDef
-
-       redef fun cs_modifiers do
-               var res = super
-               res.add "type"
-               return res
-       end
-
-       # Short signature for `MVirtualType` is always empty.
-       redef fun cs_short_signature do return ""
-
-       redef fun cs_signature do
-               var tpl = new FlatBuffer
-               if bound == null then return tpl.write_to_string
-               tpl.append ": "
-               tpl.append bound.cs_signature
-               return tpl.write_to_string
-       end
-       redef fun cs_icon do return "V"
-end
-
-redef class MType
-       # Returns the signature of this type whithout bounds.
-       fun cs_short_signature: String is abstract
-
-       # Returns the signature of this type.
-       fun cs_signature: String is abstract
-
-       redef fun cs_icon do return "T"
-end
-
-redef class MClassType
-       redef fun cs_short_signature do return cs_name
-       redef fun cs_signature do return cs_name
-end
-
-redef class MNullableType
-
-       redef fun cs_short_signature do
-               var tpl = new FlatBuffer
-               tpl.append "nullable "
-               tpl.append mtype.cs_short_signature
-               return tpl.write_to_string
-       end
-
-       redef fun cs_signature do
-               var tpl = new FlatBuffer
-               tpl.append "nullable "
-               tpl.append mtype.cs_signature
-               return tpl.write_to_string
-       end
-end
-
-redef class MGenericType
-       redef fun cs_short_signature do
-               var tpl = new FlatBuffer
-               tpl.append name
-               tpl.append "["
-               for i in [0..arguments.length[ do
-                       tpl.append arguments[i].cs_short_signature
-                       if i < arguments.length - 1 then tpl.append ", "
-               end
-               tpl.append "]"
-               return tpl.write_to_string
-       end
-
-       redef fun cs_signature do
-               var tpl = new FlatBuffer
-               tpl.append mclass.name
-               tpl.append "["
-               for i in [0..arguments.length[ do
-                       tpl.append arguments[i].cs_signature
-                       if i < arguments.length - 1 then tpl.append ", "
-               end
-               tpl.append "]"
-               return tpl.write_to_string
-       end
-end
-
-redef class MParameterType
-       redef fun cs_short_signature do return cs_name
-       redef fun cs_signature do return cs_name
-end
-
-redef class MVirtualType
-       redef fun cs_signature do return cs_name
-end
-
-redef class MSignature
-
-       redef fun cs_short_signature do
-               var tpl = new FlatBuffer
-               if not mparameters.is_empty then
-                       tpl.append "("
-                       for i in [0..mparameters.length[ do
-                               tpl.append mparameters[i].cs_short_signature
-                               if i < mparameters.length - 1 then tpl.append ", "
-                       end
-                       tpl.append ")"
-               end
-               return tpl.write_to_string
-       end
-
-       redef fun cs_signature do
-               var tpl = new FlatBuffer
-               if not mparameters.is_empty then
-                       tpl.append "("
-                       for i in [0..mparameters.length[ do
-                               tpl.append mparameters[i].cs_signature
-                               if i < mparameters.length - 1 then tpl.append ", "
-                       end
-                       tpl.append ")"
-               end
-               if return_mtype != null then
-                       tpl.append ": "
-                       tpl.append return_mtype.cs_signature
-               end
-               return tpl.write_to_string
-       end
-end
-
-redef class MParameter
-
-       # Returns `self` name and ellipsys if any.
-       fun cs_short_signature: String do
-               var tpl = new FlatBuffer
-               tpl.append name
-               if is_vararg then tpl.append "..."
-               return tpl.write_to_string
-       end
-
-       # Returns `self` name with it's static type and ellipsys if any.
-       fun cs_signature: String do
-               var tpl = new FlatBuffer
-               tpl.append "{name}: "
-               tpl.append mtype.cs_signature
-               if is_vararg then tpl.append "..."
-               return tpl.write_to_string
-       end
-end
-
-################################################################################
-# Additions to `model_ext`.
-
-redef class MRawType
-       redef fun cs_signature do
-               var tpl = new FlatBuffer
-
-               for part in parts do
-                       if part.target != null then
-                               tpl.append part.target.as(not null).cs_name
-                       else
-                               tpl.append part.text
-                       end
-               end
-               return tpl.write_to_string
-       end
-end
-
-redef class MInnerClass
-       redef fun cs_signature do return inner.cs_signature
-end
-
-redef class MInnerClassDef
-       redef fun cs_signature do return inner.cs_signature
-end
diff --git a/src/doc/console_templates/console_templates.nit b/src/doc/console_templates/console_templates.nit
deleted file mode 100644 (file)
index fbeea29..0000000
+++ /dev/null
@@ -1,139 +0,0 @@
-# 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.
-
-# Introduces templates that compose the documentation in console rendering.
-module console_templates
-
-import console_model
-import doc_phases::doc_structure
-
-# Renders the page displayable as ASCII.
-redef class DocPage
-       super Template
-
-       # Renders the footer and content.
-       private fun render_content do add root
-
-       # Renders the whole page
-       redef fun rendering do render_content
-end
-
-redef class DocComposite
-       super Template
-
-       # Title that can be decorated for console display.
-       #
-       # Set as `null` if you don't want to display a title.
-       var cs_title: nullable String is writable, lazy do return title
-
-       # Subtitle that can be decorated for console display.
-       #
-       # Set as `null` if you don't want to display a subtitle.
-       var cs_subtitle: nullable String is noinit, writable
-
-       # Renders the element `cs_title` and `cs_subtitle` as any.
-       fun render_title do
-               if cs_title != null then
-                       add "{"#" * depth} ".blue.bold
-                       addn cs_title.blue.bold
-               end
-               if cs_subtitle != null then
-                       addn cs_subtitle.gray.bold
-               end
-               if cs_title != null or cs_subtitle != null then addn ""
-       end
-
-       # Renders the element body.
-       fun render_body do for child in children do add child.write_to_string
-
-       redef fun rendering do
-               render_title
-               render_body
-       end
-end
-
-redef class DocRoot
-       redef fun rendering do render_body
-end
-
-redef class ConcernSection
-       redef var cs_title is lazy do return "in {mentity.cs_namespace}"
-       redef var cs_subtitle is lazy do return mentity.cs_declaration
-
-       redef fun rendering do
-               var mentity = self.mentity
-               if mentity isa MGroup and mentity.mpackage.root == mentity then
-                       render_body
-               else
-                       super
-               end
-       end
-end
-
-redef class MEntityComposite
-       redef var cs_title is lazy do return mentity.cs_name
-       redef var cs_subtitle is lazy do return mentity.cs_namespace
-end
-
-redef class IntroArticle
-       redef fun render_body do
-               addn "    {mentity.cs_declaration.bold}"
-               addn "    {mentity.cs_location.gray.bold}"
-               addn ""
-               var comment = mentity.cs_comment
-               if comment != null then
-                       add comment
-               end
-               addn ""
-               super
-       end
-end
-
-redef class ConcernsArticle
-       redef fun render_body do
-               var w = new StringWriter
-               concerns.write_to(w)
-               addn w.to_s
-       end
-end
-
-redef class DefinitionArticle
-       # If short, displays only synopsyses.
-       var is_short = false is writable
-
-       redef fun render_body do
-               addn "    {mentity.cs_visibility_color(mentity.cs_declaration).bold}"
-               addn "    {mentity.cs_location.gray.bold}"
-               addn ""
-               var comment
-               if is_short then
-                       comment = mentity.cs_short_comment
-               else
-                       comment = mentity.cs_comment
-               end
-               if comment != null then
-                       add comment
-               end
-               addn ""
-               super
-       end
-end
-
-redef class MEntitiesListArticle
-       redef fun render_body do
-               for mentity in mentities do
-                       addn mentity.cs_short_list_item
-               end
-       end
-end
diff --git a/src/doc/doc_phases/doc_console.nit b/src/doc/doc_phases/doc_console.nit
deleted file mode 100644 (file)
index 6a5d045..0000000
+++ /dev/null
@@ -1,549 +0,0 @@
-# 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.
-
-# Nitx related components
-#
-# This module is a place holder for `nitx` related services.
-# No `doc_phase` can be found here, only components used by Nitx tool.
-module doc_console
-
-import semantize
-import doc_commands
-import doc_poset
-import doc::console_templates
-import model::model_index
-
-# Nitx handles console I/O.
-#
-# Using `prompt`, the command line can be turned on an interactive tool.
-class Nitx
-
-       # ToolContext used to access options.
-       var ctx: ToolContext
-
-       # DocModel that contains the informations to display.
-       var doc: DocModel
-
-       # Comparator used to sort MEntities.
-       var sorter = new MEntityNameSorter
-
-       # Displays the welcome message and start prompt.
-       fun start do
-               welcome
-               prompt
-       end
-
-       # Displays the welcome message and the list of loaded modules.
-       fun welcome do
-               print "Welcome in the Nit Index."
-               print ""
-               print "Loaded modules:"
-               var mmodules = doc.mmodules.to_a
-               sorter.sort(mmodules)
-               for m in mmodules do
-                       print "\t{m.name}"
-               end
-               print ""
-               help
-       end
-
-       # Displays the list of available commands.
-       fun help do
-               print "\nCommands:\n"
-               print "\tname\t\t\tlookup module, class and property with the corresponding 'name'"
-               print "\tdoc: <name::space>\tdisplay the documentation page of 'namespace'"
-               print "\nType lookup:"
-               print "\tparam: <Type>\t\tlookup methods using the corresponding 'Type' as parameter"
-               print "\treturn: <Type>\t\tlookup methods returning the corresponding 'Type'"
-               print "\tnew: <Type>\t\tlookup methods creating new instances of 'Type'"
-               print "\tcall: <name>\t\tlookup methods calling 'name'"
-               print "\nHierarchy lookup:"
-               print "\tparents: <Class>\tlist direct parents of 'Class'"
-               print "\tancestors: <Class>\tlist all ancestors of 'Class'"
-               print "\tchildren: <Class>\tlist direct children of 'Class'"
-               print "\tdescendants: <Class>\tlist all descendants of 'Class'"
-               print "\nCode lookup:"
-               print "\tcode: <name>\t\tdisplay the source code associated to the 'name' entity"
-               print "\n"
-               print "\t:h\t\t\tdisplay this help message"
-               print "\t:q\t\t\tquit interactive mode"
-               print ""
-       end
-
-       # Prompts the user for a command.
-       fun prompt do
-               printn ">> "
-               do_query(sys.stdin.read_line)
-               prompt
-       end
-
-       # Parser used to process doc commands
-       var parser: DocCommandParser is lazy do
-               var parser = new DocCommandParser
-               parser.allowed_commands = ["doc", "comment", "list", "param", "return",
-                       "new", "call", "code"]
-               return parser
-       end
-
-       # Processes the query string and performs it.
-       fun do_query(str: String) do
-               if str == ":q" then
-                       exit 0
-               else if str == ":h" then
-                       help
-                       return
-               end
-               var query = parser.parse(str)
-               if query == null then
-                       query = new CommentCommand(str)
-                       query.arg = str
-               end
-               var res = query.perform(self, doc)
-               var suggest = null
-               if res.is_empty then
-                       suggest = query.suggest(self, doc)
-               end
-               var page = query.make_results(self, res, suggest)
-               print page.write_to_string
-       end
-end
-
-redef class DocCommand
-
-       # Looks up the `doc` model and returns possible matches.
-       fun perform(nitx: Nitx, doc: DocModel): Array[NitxMatch] is abstract
-
-       # Looks up the `doc` model and returns possible suggestions.
-       fun suggest(nitx: Nitx, doc: DocModel): nullable Array[MEntity] do
-               return find_suggestions(doc, arg)
-       end
-
-       # Pretty prints the results for the console.
-       fun make_results(nitx: Nitx, results: Array[NitxMatch], suggest: nullable Array[MEntity]): DocPage do
-               var page = new DocPage("results", "Results")
-               page.root.add_child(new QueryResultArticle("results", "Results", self, results, suggest))
-               return page
-       end
-
-       # Lookup mentities based on a `query` string.
-       #
-       # 1- lookup by first name (returns always one value)
-       # 2- lookup by name (can return conflicts)
-       fun find_mentities(doc: DocModel, query: String): Array[MEntityMatch] do
-               var res = new Array[MEntityMatch]
-
-               # First lookup by full_name
-               var mentity = doc.mentity_by_full_name(query)
-               if mentity != null then
-                       res.add new MEntityMatch(self, mentity)
-                       return res
-               end
-
-               # If no results, lookup by name
-               for m in doc.mentities_by_name(query) do
-                       res.add new MEntityMatch(self, m)
-               end
-
-               return res
-       end
-
-       # Suggest some mentities based on a `query` string.
-       fun find_suggestions(doc: DocModel, query: String): Array[MEntity] do
-               return doc.find(query, 3)
-       end
-end
-
-# Something that matches a `DocCommand`.
-abstract class NitxMatch
-
-       # Query matched by `self`.
-       var query: DocCommand
-
-       # Pretty prints `self` for console.
-       fun make_list_item: String is abstract
-end
-
-# A match between a `DocCommand` and a `MEntity`.
-class MEntityMatch
-       super NitxMatch
-
-       # MEntity matched.
-       var mentity: MEntity
-
-       redef fun make_list_item do return mentity.cs_list_item
-end
-
-redef class CommentCommand
-       redef fun perform(nitx, doc) do return find_mentities(doc, arg)
-
-       redef fun make_results(nitx, results, suggest) do
-               var len = results.length
-               if len == 1 then
-                       var res = results.first.as(MEntityMatch)
-                       var mentity = res.mentity
-                       var page = new DocPage("resultats", "Results")
-                       var article = new DefinitionArticle("results", "Results", mentity)
-                       article.cs_title = mentity.name
-                       article.cs_subtitle = mentity.cs_declaration
-                       page.root.add_child article
-                       return page
-               else
-                       return super
-               end
-       end
-end
-
-# A query to search signatures using a specific `MType` as parameter.
-redef class ParamCommand
-       redef fun perform(nitx, doc) do
-               var res = new Array[NitxMatch]
-               var mtype_name = arg
-               for mproperty in doc.mproperties do
-                       if not mproperty isa MMethod then continue
-                       var msignature = mproperty.intro.msignature
-                       if msignature != null then
-                               for mparam in msignature.mparameters do
-                                       if mparam.mtype.name == mtype_name then
-                                               res.add new MEntityMatch(self, mproperty)
-                                       end
-                               end
-                       end
-               end
-               return res
-       end
-end
-
-# A query to search signatures using a specific `MType` as return.
-redef class ReturnCommand
-       redef fun perform(nitx, doc) do
-               var res = new Array[NitxMatch]
-               var mtype_name = arg
-               for mproperty in doc.mproperties do
-                       if not mproperty isa MMethod then continue
-                       var msignature = mproperty.intro.msignature
-                       if msignature != null then
-                               var mreturn = msignature.return_mtype
-                               if mreturn != null and mreturn.name == mtype_name then
-                                       res.add new MEntityMatch(self, mproperty)
-                               end
-                       end
-               end
-               return res
-       end
-end
-
-# A query to search methods creating new instances of a specific `MType`.
-redef class NewCommand
-       redef fun perform(nitx, doc) do
-               var res = new Array[NitxMatch]
-               var mtype_name = arg
-               for mpropdef in doc.mpropdefs do
-                       var visitor = new TypeInitVisitor(mtype_name)
-                       var npropdef = nitx.ctx.modelbuilder.mpropdef2node(mpropdef)
-                       if npropdef == null then continue
-                       visitor.enter_visit(npropdef)
-                       for i in visitor.inits do
-                               res.add new MEntityMatch(self, mpropdef)
-                       end
-               end
-               return res
-       end
-end
-
-# A query to search methods calling a specific `MProperty`.
-redef class CallCommand
-       redef fun perform(nitx, doc) do
-               var res = new Array[NitxMatch]
-               var mprop_name = arg
-               for mpropdef in doc.mpropdefs do
-                       var visitor = new MPropertyCallVisitor
-                       var npropdef = nitx.ctx.modelbuilder.mpropdef2node(mpropdef)
-                       if npropdef == null then continue
-                       visitor.enter_visit(npropdef)
-                       for mprop in visitor.calls do
-                               if mprop.name != mprop_name then continue
-                               res.add new MEntityMatch(self, mpropdef)
-                       end
-               end
-               return res
-       end
-end
-
-# A match between a `DocPage` and a `MEntity`.
-class PageMatch
-       super NitxMatch
-
-       # `DocPage` matched.
-       var page: DocPage
-
-       redef fun make_list_item do
-               var page = self.page
-               if page isa MEntityPage then
-                       return page.mentity.cs_list_item
-               end
-               return " * {page.title}"
-       end
-end
-
-# Search in class or module hierarchy of a `MEntity`.
-#
-# It actually searches for pages about the mentity and extracts the
-# pre-calculated hierarchies by the `doc_post` phase.
-abstract class HierarchiesQuery
-       super DocCommand
-
-       redef fun make_results(nitx, results, suggest) do
-               var page = new DocPage("hierarchy", "Hierarchy")
-               for result in results do
-                       if not result isa PageMatch then continue
-                       var rpage = result.page
-                       if not rpage isa MClassPage then continue
-                       page.root.add_child build_article(rpage)
-               end
-               return page
-       end
-
-       # Build an article containing the hierarchy list depending on subclasses.
-       private fun build_article(page: MClassPage): DocArticle is abstract
-end
-
-# List all parents of a `MClass`.
-class AncestorsQuery
-       super HierarchiesQuery
-
-       redef fun build_article(page) do
-               return new MEntitiesListArticle(
-                       "ancerstors",
-                       "Ancestors for {page.mentity.name}",
-                       page.ancestors.to_a)
-       end
-end
-
-# List direct parents of a `MClass`.
-class ParentsQuery
-       super HierarchiesQuery
-
-       redef fun build_article(page) do
-               return new MEntitiesListArticle(
-                       "parents",
-                       "Parents for {page.mentity.name}",
-                       page.parents.to_a)
-       end
-end
-
-# List direct children of a `MClass`.
-class ChildrenQuery
-       super HierarchiesQuery
-
-       redef fun build_article(page) do
-               return new MEntitiesListArticle(
-                       "children",
-                       "Children for {page.mentity.name}",
-                       page.children.to_a)
-       end
-end
-
-# List all descendants of a `MClass`.
-class DescendantsQuery
-       super HierarchiesQuery
-
-       redef fun build_article(page) do
-               return new MEntitiesListArticle(
-                       "descendants",
-                       "Descendants for {page.mentity.name}",
-                       page.children.to_a)
-       end
-end
-
-# A query to search source code from a file name.
-redef class CodeCommand
-       # FIXME refactor this!
-       redef fun perform(nitx, doc) do
-               var res = new Array[NitxMatch]
-               var name = arg
-               # if name is an existing sourcefile, opens it
-               if name.file_exists then
-                       var fr = new FileReader.open(name)
-                       var content = fr.read_all
-                       fr.close
-                       res.add new CodeMatch(self, name, content)
-                       return res
-               end
-               # else, lookup the model by name
-               for match in find_mentities(doc, name) do
-                       if match.mentity isa MClass then continue
-                       if match.mentity isa MProperty then continue
-                       res.add new CodeMatch(self, match.mentity.cs_location, match.mentity.cs_source_code)
-               end
-               return res
-       end
-
-       redef fun make_results(nitx, results, suggest) do
-               var page = new DocPage("results", "Code Results")
-               for res in results do
-                       page.add new CodeQueryArticle("results", "Results", self, res.as(CodeMatch))
-               end
-               return page
-       end
-end
-
-# A match between a piece of code and a string.
-class CodeMatch
-       super NitxMatch
-
-       # Location of the code match.
-       var location: String
-
-       # Piece of code matched.
-       var content: String
-
-       redef fun make_list_item do return "* {location}"
-end
-
-## exploration
-
-# Visitor looking for initialized `MType` (new T).
-#
-# See `NewQuery`.
-private class TypeInitVisitor
-       super Visitor
-
-       # `MType` name to look for.
-       var mtype_name: String
-
-       var inits = new HashSet[MType]
-       redef fun visit(node)
-       do
-               node.visit_all(self)
-               # look for init
-               if not node isa ANewExpr then return
-               var mtype = node.n_type.mtype
-               if mtype != null and mtype.name == mtype_name then inits.add(mtype)
-       end
-end
-
-# Visitor looking for calls to a `MProperty` (new T).
-#
-# See `CallQuery`.
-private class MPropertyCallVisitor
-       super Visitor
-
-       var calls = new HashSet[MProperty]
-       redef fun visit(node)
-       do
-               node.visit_all(self)
-               if not node isa ASendExpr then return
-               calls.add node.callsite.as(not null).mproperty
-       end
-end
-
-# display
-
-# A `DocArticle` that displays query results.
-private class QueryResultArticle
-       super DocArticle
-
-       # Query linked to the results to display.
-       var query: DocCommand
-
-       # Results to display.
-       var results: Array[NitxMatch]
-
-       # Optional suggestion when no matches where found
-       var suggest: nullable Array[MEntity] = null is optional
-
-       redef fun render_title do
-               var len = results.length
-               if len == 0 then
-                       addn "No result found for '{query.string}'..."
-                       var suggest = self.suggest
-                       if suggest != null and suggest.not_empty then
-                               add "\nDid you mean "
-                               var i = 0
-                               for s in suggest do
-                                       add "`{s.full_name}`"
-                                       if i == suggest.length - 2 then add ", "
-                                       if i == suggest.length - 1 then add " or "
-                                       i += 1
-                               end
-                               add "?"
-                       end
-               else
-                       add "# {len} result(s) for '{query.string}'".green.bold
-               end
-       end
-
-       redef fun render_body do
-               addn ""
-               for result in results do
-                       addn ""
-                       addn result.make_list_item
-               end
-       end
-end
-
-# An article that displays a piece of code.
-private class CodeQueryArticle
-       super DocArticle
-
-       # The query linked to the result to display.
-       var query: DocCommand
-
-       # The result to display.
-       var result: CodeMatch
-
-       redef fun render_body do
-               addn ""
-               addn "in {result.location}".gray.bold
-               addn ""
-               add result.content
-       end
-end
-
-# A Pager is used to display data into a unix `less` container.
-private class Pager
-
-       # Content to display.
-       var content = new FlatBuffer
-
-       # Adds text to the pager.
-       fun add(text: String) do
-               content.append(escape(text))
-       end
-
-       fun render do sys.system("echo \"{content}\" | less -r")
-
-       fun escape(str: String): String
-       do
-               var b = new FlatBuffer
-               for c in str.chars do
-                       if c == '\n' then
-                               b.append("\\n")
-                       else if c == '\0' then
-                               b.append("\\0")
-                       else if c == '"' then
-                               b.append("\\\"")
-                       else if c == '\\' then
-                               b.append("\\\\")
-                       else if c == '`' then
-                               b.append("'")
-                       else if c.code_point < 32 then
-                               b.append("\\{c.code_point.to_base(8)}")
-                       else
-                               b.add(c)
-                       end
-               end
-               return b.to_s
-       end
-end
diff --git a/src/doc/templates/templates_term.nit b/src/doc/templates/templates_term.nit
new file mode 100644 (file)
index 0000000..b4fc2fe
--- /dev/null
@@ -0,0 +1,311 @@
+# 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.
+
+# Markdown templates for Nit model MEntities.
+#
+# This module introduces Markdown rendering services in model entities.
+# With the `no_color` option set to `false`, the output can be highlighted for console.
+module templates_term
+
+import model_collect
+import console
+
+redef class MDoc
+       # Returns the full comment formatted for the console
+       fun cs_comment(no_color: nullable Bool, indent: nullable Int): String do
+               var res = new FlatBuffer
+               indent = indent or else 0
+               for line in content do
+                       res.append "{" " * indent}{line}\n"
+               end
+               if no_color == null or not no_color then
+                       return res.write_to_string.green
+               end
+               return res.write_to_string
+       end
+
+       # Returns the synopsys formatted for the console
+       fun cs_short_comment(no_color: nullable Bool): String do
+               if no_color == null or not no_color then
+                       return content.first.green
+               end
+               return content.first
+       end
+end
+
+redef class MEntity
+
+       # Text icon to be displayed in front of the entity
+       fun cs_icon(no_color: nullable Bool): String do
+               return public_visibility.cs_icon(no_color)
+       end
+
+       # Source code location of this MEntity formatted for console
+       fun cs_location(no_color: nullable Bool): String do
+               if no_color == null or not no_color then
+                       return location.to_s.bold.gray
+               end
+               return location.to_s
+       end
+
+       # Returns `self.full_name` formatted for console
+       fun cs_full_name(no_color: nullable Bool): String do
+               if no_color == null or not no_color then
+                       return full_name.bold.blue
+               end
+               return full_name
+       end
+
+       # Returns `self` signature formatted for console.
+       fun cs_signature(no_color: nullable Bool): String do return ""
+
+       # Returns the comment of this MEntity formatted for console.
+       fun cs_comment(no_color: nullable Bool): nullable String do
+               var mdoc = mdoc_or_fallback
+               if mdoc == null then return null
+               # FIXME add markdown for console
+               return mdoc.cs_comment(no_color)
+       end
+
+       # Returns the comment of this MEntity formatted for console.
+       fun cs_short_comment(no_color: nullable Bool): nullable String do
+               var mdoc = mdoc_or_fallback
+               if mdoc == null then return null
+               return mdoc.cs_short_comment(no_color)
+       end
+
+       # Returns the complete MEntity declaration (modifiers + name + signature).
+       #
+       # * MPackage: `package foo`
+       # * MGroup: `group foo`
+       # * MModule: `module foo`
+       # * MClass: `private abstract class Foo[E: Object]`
+       # * MClassDef: `redef class Foo[E]`
+       # * MProperty: `private fun foo(e: Object): Int`
+       # * MPropdef: `redef fun foo(e)`
+       fun cs_declaration(no_color: nullable Bool): String do
+               var tpl = new FlatBuffer
+               tpl.append collect_modifiers.join(" ")
+               tpl.append " "
+               tpl.append name
+               tpl.append cs_signature(no_color)
+               if no_color == null or not no_color then
+                       return tpl.write_to_string.bold
+               end
+               return tpl.write_to_string
+       end
+
+       # Returns `self` as a list element that can be displayed in console.
+       #
+       # Displays `cs_icon`, `cs_name`, `cs_short_comment, `cs_namespace`,
+       # `cs_declaration` and `cs_location`.
+       fun cs_list_item(no_color: nullable Bool): String do
+               var tpl = new FlatBuffer
+               tpl.append " "
+               tpl.append cs_icon(no_color)
+               tpl.append " "
+               tpl.append cs_full_name(no_color)
+               var comment = cs_short_comment(no_color)
+               if comment != null then
+                       tpl.append "\n   "
+                       if no_color == null or not no_color then
+                               tpl.append "# ".green
+                       else
+                               tpl.append "# "
+                       end
+                       tpl.append comment
+               end
+               tpl.append "\n   "
+               tpl.append cs_declaration(no_color)
+               tpl.append "\n   "
+               tpl.append cs_location(no_color)
+               return tpl.write_to_string
+       end
+
+       # Source code associated to this MEntity.
+       #
+       # Uses `cs_location` to locate the source code.
+       fun cs_source_code: String do
+               var tpl = new Buffer
+               tpl.append "\n~~~\n"
+               tpl.append location.text
+               tpl.append "\n~~~\n"
+               return tpl.write_to_string
+       end
+end
+
+redef class MClass
+       redef fun cs_icon(no_color) do return intro.cs_icon(no_color)
+       redef fun cs_signature(no_color) do return intro.cs_signature(no_color)
+end
+
+redef class MClassDef
+       redef fun cs_icon(no_color) do
+               if is_intro then return visibility.cs_icon(no_color)
+               return visibility.cs_visibility_color("*")
+       end
+
+       # Returns the MClassDef generic signature with static bounds.
+       redef fun cs_signature(no_color) do
+               var tpl = new FlatBuffer
+               var mparameters = mclass.mparameters
+               if not mparameters.is_empty then
+                       tpl.append "["
+                       for i in [0..mparameters.length[ do
+                               tpl.append "{mparameters[i].name}: "
+                               tpl.append bound_mtype.arguments[i].cs_signature(no_color)
+                               if i < mparameters.length - 1 then tpl.append ", "
+                       end
+                       tpl.append "]"
+               end
+               return tpl.write_to_string
+       end
+end
+
+redef class MProperty
+       redef fun cs_icon(no_color) do return intro.cs_icon(no_color)
+       redef fun cs_signature(no_color) do return intro.cs_signature(no_color)
+end
+
+redef class MPropDef
+       redef fun cs_icon(no_color) do
+               if is_intro then return visibility.cs_icon(no_color)
+               return visibility.cs_visibility_color("*", no_color)
+       end
+end
+
+redef class MAttributeDef
+       redef fun cs_signature(no_color) do
+               var tpl = new FlatBuffer
+               var static_mtype = self.static_mtype
+               if static_mtype != null then
+                       tpl.append ": "
+                       tpl.append static_mtype.cs_signature(no_color)
+               end
+               return tpl.write_to_string
+       end
+end
+
+redef class MMethodDef
+       redef fun cs_signature(no_color) do
+               if mproperty.is_root_init then
+                       return new_msignature.as(not null).cs_signature(no_color)
+               end
+               return msignature.as(not null).cs_signature(no_color)
+       end
+end
+
+redef class MVirtualTypeDef
+       redef fun cs_signature(no_color) do
+               var tpl = new FlatBuffer
+               var bound = self.bound
+               if bound == null then return tpl.write_to_string
+               tpl.append ": "
+               tpl.append bound.cs_signature(no_color)
+               return tpl.write_to_string
+       end
+end
+
+redef class MClassType
+       redef fun cs_signature(no_color) do return name
+end
+
+redef class MNullableType
+       redef fun cs_signature(no_color) do
+               var tpl = new FlatBuffer
+               tpl.append "nullable "
+               tpl.append mtype.cs_signature(no_color)
+               return tpl.write_to_string
+       end
+end
+
+redef class MGenericType
+       redef fun cs_signature(no_color) do
+               var tpl = new FlatBuffer
+               tpl.append mclass.name
+               tpl.append "["
+               for i in [0..arguments.length[ do
+                       tpl.append arguments[i].cs_signature(no_color)
+                       if i < arguments.length - 1 then tpl.append ", "
+               end
+               tpl.append "]"
+               return tpl.write_to_string
+       end
+end
+
+redef class MParameterType
+       redef fun cs_signature(no_color) do return name
+end
+
+redef class MVirtualType
+       redef fun cs_signature(no_color) do return name
+end
+
+redef class MSignature
+       redef fun cs_signature(no_color) do
+               var tpl = new FlatBuffer
+               if not mparameters.is_empty then
+                       tpl.append "("
+                       for i in [0..mparameters.length[ do
+                               tpl.append mparameters[i].cs_signature(no_color)
+                               if i < mparameters.length - 1 then tpl.append ", "
+                       end
+                       tpl.append ")"
+               end
+               var return_mtype = self.return_mtype
+               if return_mtype != null then
+                       tpl.append ": "
+                       tpl.append return_mtype.cs_signature(no_color)
+               end
+               return tpl.write_to_string
+       end
+end
+
+redef class MParameter
+       redef fun cs_signature(no_color) do
+               var tpl = new FlatBuffer
+               tpl.append "{name}: "
+               tpl.append mtype.cs_signature(no_color)
+               if is_vararg then tpl.append "..."
+               return tpl.write_to_string
+       end
+end
+
+redef class MVisibility
+       # Visibility icon
+       fun cs_icon(no_color: nullable Bool): String do
+               var icon
+               if self == private_visibility then
+                       icon = cs_visibility_color("-", no_color)
+               else if self == protected_visibility then
+                       icon = cs_visibility_color("#", no_color)
+               else
+                       icon = cs_visibility_color("+", no_color)
+               end
+               if no_color != null and no_color then return icon
+               return icon.bold
+       end
+
+       # Colorize `string` depending on the visibility
+       fun cs_visibility_color(string: String, no_color: nullable Bool): String do
+               if no_color != null and no_color then return string
+               if self == private_visibility then
+                       return string.red
+               else if self == protected_visibility then
+                       return string.yellow
+               else
+                       return string.green
+               end
+       end
+end
diff --git a/src/doc/term/term.nit b/src/doc/term/term.nit
new file mode 100644 (file)
index 0000000..33b5221
--- /dev/null
@@ -0,0 +1,337 @@
+# 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.
+
+module term
+
+import commands::commands_parser
+import templates::templates_term
+
+redef class CommandParser
+
+       fun execute(query: String, no_color: nullable Bool) do
+               var cmd = self.parse(query)
+               var error = self.error
+
+               # If not a command, try a comment query
+               if cmd == null and error isa CmdParserError then
+                       error = null
+                       cmd = new CmdComment(view, mentity_name = query)
+                       var opts = new HashMap[String, String]
+                       var status = cmd.parser_init(query, opts)
+                       if not status isa CmdSuccess then error = status
+               end
+
+               if error isa CmdError or error isa CmdWarning then
+                       error.print_message(no_color)
+                       print ""
+               end
+               cmd.as(not null).execute(no_color)
+       end
+end
+
+redef class DocCommand
+       fun execute(no_color: nullable Bool) is abstract
+end
+
+redef class CmdMessage
+       fun print_message(no_color: nullable Bool) do print to_s
+end
+
+redef class CmdError
+       redef fun print_message(no_color) do
+               var res = "Error: {to_s}"
+               if no_color == null or not no_color then res = res.bold.red
+               print res
+       end
+end
+
+redef class CmdWarning
+       redef fun print_message(no_color) do
+               var res = "Warning: {to_s}"
+               if no_color == null or not no_color then res = res.bold.yellow
+               print res
+       end
+end
+
+# Model queries
+
+redef class ErrorMEntityNotFound
+       redef fun print_message(no_color) do
+               if no_color == null or not no_color then
+                       print "No result found for `{mentity_name.blue}`...".bold
+               else
+                       print "No result found for `{mentity_name}`..."
+               end
+               print ""
+               if suggestions.not_empty then
+                       print "Did you mean?"
+                       print ""
+                       for s in suggestions do
+                               print s.cs_list_item(no_color)
+                               print ""
+                       end
+               end
+       end
+end
+
+redef class ErrorMEntityConflict
+       redef fun print_message(no_color) do
+               if no_color == null or not no_color then
+                       print "Multiple results found for `{mentity_name.blue}`...".bold
+               else
+                       print "Multiple results found for `{mentity_name}`..."
+               end
+               print ""
+               if conflicts.not_empty then
+                       print "Did you mean?"
+                       print ""
+                       for s in conflicts do
+                               print s.cs_list_item(no_color)
+                               print ""
+                       end
+               end
+       end
+end
+
+redef class CmdList
+       fun print_list(list_title: nullable String, list_items: nullable Array[MEntity], no_color: nullable Bool) do
+               if list_title != null then
+                       if no_color == null or not no_color then
+                               print list_title.bold
+                       else
+                               print list_title
+                       end
+                       print ""
+               end
+               if list_items != null and list_items.not_empty then
+                       for mentity in list_items do
+                               print mentity.cs_list_item(no_color)
+                               print ""
+                       end
+               else
+                       print "None."
+               end
+       end
+end
+
+redef class CmdComment
+       redef fun execute(no_color) do
+               var mentity = self.mentity
+               if mentity == null then return
+
+               var full_name = mentity.cs_full_name(no_color)
+               if no_color == null or not no_color then
+                       print "Documentation for `{full_name}`:".bold
+               else
+                       print "Documentation for `{full_name}`:"
+               end
+               print ""
+               print " {mentity.cs_icon(no_color)} {mentity.cs_full_name(no_color)}"
+               print "   {mentity.cs_declaration(no_color)}"
+               print "   {mentity.cs_location(no_color)}"
+               print ""
+               var mdoc = self.mdoc
+               if mdoc == null then return
+               if full_doc then
+                       print mdoc.cs_comment(no_color, 3)
+               else
+                       print "   {mdoc.cs_short_comment(no_color)}\n"
+               end
+       end
+end
+
+redef class CmdAncestors
+       redef fun execute(no_color) do
+               var full_name = mentity.as(not null).cs_full_name(no_color)
+               print_list("Ancestors for `{full_name}`:", results, no_color)
+       end
+end
+
+redef class CmdParents
+       redef fun execute(no_color) do
+               var full_name = mentity.as(not null).cs_full_name(no_color)
+               print_list("Parents for `{full_name}`:", results, no_color)
+       end
+end
+
+redef class CmdChildren
+       redef fun execute(no_color) do
+               var full_name = mentity.as(not null).cs_full_name(no_color)
+               print_list("Children for `{full_name}`:", results, no_color)
+       end
+end
+
+redef class CmdDescendants
+       redef fun execute(no_color) do
+               var full_name = mentity.as(not null).cs_full_name(no_color)
+               print_list("Descendants for `{full_name}`:", results, no_color)
+       end
+end
+
+redef class CmdLinearization
+       redef fun execute(no_color) do
+               var full_name = mentity.as(not null).cs_full_name(no_color)
+               print_list("Linearization for `{full_name}`:", results, no_color)
+       end
+end
+
+redef class CmdSearch
+       redef fun execute(no_color) do
+               print_list("Search results for `{query.as(not null)}`:", results, no_color)
+       end
+end
+
+redef class CmdModelEntities
+       redef fun execute(no_color) do
+               var kind = self.kind
+               if no_color != null and not no_color then kind = kind.blue
+               print_list("MEntities for kind `{kind}`:", results, no_color)
+       end
+end
+
+redef class CmdFeatures
+       redef fun execute(no_color) do
+               var full_name = mentity.as(not null).cs_full_name(no_color)
+               print_list("Features for `{full_name}`:", results, no_color)
+       end
+end
+
+redef class CmdCode
+       redef fun execute(no_color) do
+               var mentity = self.mentity
+               if mentity == null then return
+
+               var title = "Code for `{mentity.cs_full_name(no_color)}`:"
+               if no_color == null or not no_color then
+                       print title.bold
+               else
+                       print title
+               end
+               printn mentity.cs_source_code
+       end
+end
+
+redef class CmdGraph
+       redef fun execute(no_color) do
+               format = "dot"
+               var dot = self.render
+               if dot == null then return
+               var f = new ProcessWriter("dot", "-Txlib")
+               f.write dot.write_to_string
+               f.close
+               f.wait
+       end
+end
+
+# CmdUsage
+
+redef class CmdCall
+       redef fun execute(no_color) do
+               var full_name = mentity.as(not null).cs_full_name(no_color)
+               print_list("Methods calling `{full_name}`:", results, no_color)
+       end
+end
+
+redef class CmdNew
+       redef fun execute(no_color) do
+               var full_name = mentity.as(not null).cs_full_name(no_color)
+               print_list("Methods intializing `{full_name}`:", results, no_color)
+       end
+end
+
+redef class CmdReturn
+       redef fun execute(no_color) do
+               var full_name = mentity.as(not null).cs_full_name(no_color)
+               print_list("Methods returning `{full_name}`:", results, no_color)
+       end
+end
+
+redef class CmdParam
+       redef fun execute(no_color) do
+               var full_name = mentity.as(not null).cs_full_name(no_color)
+               print_list("Methods accepting `{full_name}` as parameter:", results, no_color)
+       end
+end
+
+# CmdCatalog
+
+redef class CmdCatalogPackages
+       redef fun execute(no_color) do
+               print_list("Packages from catalog:", results, no_color)
+       end
+end
+
+redef class CmdCatalogStats
+       redef fun execute(no_color) do
+               if no_color == null or not no_color then
+                       print "Catalog statistics:".bold
+               else
+                       print "Catalog statistics:"
+               end
+
+               var stats = self.stats.as(not null)
+               print " * {stats.packages} packages"
+               print " * {stats.modules} modules"
+               print " * {stats.methods} methods"
+               print " * {stats.classes} classes"
+               print " * {stats.loc} lines of code"
+               print " * {stats.contributors} contributors"
+               print " * {stats.maintainers} maintainers"
+               print " * {stats.tags} tags"
+       end
+end
+
+redef class CmdCatalogTags
+       redef fun execute(no_color) do
+               if no_color == null or not no_color then
+                       print "Tags from catalog:".bold
+               else
+                       print "Tags from catalog:"
+               end
+
+               print ""
+               var counts = self.packages_count_by_tags.as(not null)
+               for tag, count in counts do
+                       if no_color == null or not no_color then
+                               print " * {tag.blue.bold}: {count} packages"
+                       else
+                               print " * {tag}: {count} packages"
+                       end
+               end
+       end
+end
+
+redef class CmdCatalogTag
+       redef fun execute(no_color) do
+               var tag = self.tag.as(not null)
+               if no_color == null or not no_color then tag = tag.blue.bold
+               print_list("Packages tagged with `{tag}`:", results, no_color)
+       end
+end
+
+redef class CmdCatalogMaintaining
+       redef fun execute(no_color) do
+               var name = self.person_name.as(not null)
+               if no_color == null or not no_color then name = name.blue.bold
+               print_list("Packages maintained by `{name}`:", results, no_color)
+       end
+end
+
+redef class CmdCatalogContributing
+       redef fun execute(no_color) do
+               var name = self.person_name.as(not null)
+               if no_color == null or not no_color then name = name.blue.bold
+               print_list("Packages contributed by `{name}`:", results, no_color)
+       end
+end
index ff97784..061b44e 100644 (file)
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-# `nitx`, is a command tool that displays useful informations about the code.
+# `nitx`, a command tool that displays useful data about Nit code
 #
 # Features:
 #
-# * Display comment from name/namespace
-# * Display documentation page from Nitdoc in console
+# * Display documentation from name/namespace
 # * Find type usage in parameters, returns and news.
-# * Find usage of a specific property.
+# * Find usage (calls) of a specific property.
 # * Find source code related to class/property by its name.
+# * Display inheritance lists
 module nitx
 
-import modelbuilder
-import doc::doc_phases::doc_console
+import frontend
+import doc::term
+import readline
 
 redef class ToolContext
 
-       # Nittx generation phase.
-       var docx: Phase = new NitxPhase(self, null)
-
        # Used to shortcut the prompt and display directly the result in console.
        var opt_command = new OptionString("Nitx command to perform", "-c", "--command")
 
-       init do option_context.add_option opt_command
+       # Compute and use the catalog
+       var opt_catalog = new OptionBool("Use catalog", "--catalog")
+
+       init do option_context.add_option(opt_command, opt_catalog)
 end
 
-# Nitx phase explores the model and prepares the console rendering.
-private class NitxPhase
-       super Phase
-       redef fun process_mainmodule(mainmodule, mmodules)
-       do
-               var doc = new DocModel(mainmodule.model, mainmodule)
-
-               var phases = [
-                       new MakePagePhase(toolcontext, doc),
-                       new ConcernsPhase(toolcontext, doc),
-                       new StructurePhase(toolcontext, doc),
-                       new POSetPhase(toolcontext, doc): DocPhase]
-
-               for phase in phases do
-                       toolcontext.info("# {phase.class_name}", 1)
-                       phase.apply
+# Nitx handles console queries
+#
+# Using `prompt`, the command line can be turned on an interactive tool.
+class Nitx
+
+       # ModelView that contains the informations to display
+       var view: ModelView
+
+       # ModelBuilder to access AST nodes
+       var modelbuilder: ModelBuilder
+
+       # Catalog if any
+       var catalog: nullable Catalog = null is optional
+
+       # Do not use colors in the output
+       var no_color = false is optional
+
+       # Displays the welcome message and start prompt.
+       fun start do
+               welcome
+               prompt
+       end
+
+       # Displays the welcome message and the list of loaded modules.
+       fun welcome do
+               print "Welcome in the Nit Index!"
+               print ""
+               print "Loaded packages:\n"
+               var cmd = new CmdModelEntities(view, kind = "packages")
+               cmd.init_command
+               for mpackage in cmd.results.as(not null) do
+                       print " * {mpackage.full_name}"
+               end
+               help
+       end
+
+       # Displays the list of available queries.
+       fun help do
+               # TODO automatize that
+               print "\nCommands:\n"
+               for usage, doc in parser.commands_usage do
+                       var l = usage.length / 8
+                       print "\t{usage}{"\t" * (3 - l)}{doc}"
+               end
+               print "\n"
+               print "\t:h\t\t\tdisplay this help message"
+               print "\t:q\t\t\tquit interactive mode"
+               print ""
+       end
+
+       # Prompts the user for a query.
+       fun prompt do
+               var line = readline(">> ", true)
+               if line != null then
+                       do_command(line)
                end
+               prompt
+       end
+
+       # Parser used to process doc commands
+       var parser = new CommandParser(view, modelbuilder, catalog) is lazy
 
-               # start nitx
-               var nitx = new Nitx(toolcontext, doc)
-               var q = toolcontext.opt_command.value
-               if q != null then # shortcut prompt
-                       print ""
-                       nitx.do_query(q)
+       # Processes the query string and performs it.
+       fun do_command(str: String) do
+               if str == ":q" then
+                       exit 0
+               else if str == ":h" then
+                       help
                        return
                end
-               nitx.start
+               parser.execute(str, no_color)
+       end
+end
+
+redef class Catalog
+       # Build the catalog for Nitx
+       private fun build_catalog(view: ModelView) do
+               # Compute the poset
+               for p in view.mpackages do
+                       var g = p.root
+                       assert g != null
+                       modelbuilder.scan_group(g)
+
+                       deps.add_node(p)
+                       for gg in p.mgroups do for m in gg.mmodules do
+                               for im in m.in_importation.direct_greaters do
+                                       var ip = im.mpackage
+                                       if ip == null or ip == p then continue
+                                       deps.add_edge(p, ip)
+                               end
+                       end
+               end
+               # Build the catalog
+               for mpackage in view.mpackages do
+                       package_page(mpackage)
+                       git_info(mpackage)
+                       mpackage_stats(mpackage)
+               end
        end
 end
 
@@ -71,7 +143,7 @@ end
 var toolcontext = new ToolContext
 var tpl = new Template
 tpl.add "Usage: nitx [OPTION]... <file.nit>... [query]\n"
-tpl.add "Displays specific pieces of API information from Nit source files."
+tpl.add "Displays pieces of API information from Nit source files."
 toolcontext.tooldescription = tpl.write_to_string
 
 # process options
@@ -87,3 +159,22 @@ var mmodules = mbuilder.parse_full(arguments)
 if mmodules.is_empty then return
 mbuilder.run_phases
 toolcontext.run_global_phases(mmodules)
+var mainmodule = toolcontext.make_main_module(mmodules)
+
+# build views
+var view = new ModelView(model, mainmodule)
+var catalog = null
+if toolcontext.opt_catalog.value then
+       catalog = new Catalog(mbuilder)
+       catalog.build_catalog(view)
+end
+
+# start nitx
+var nitx = new Nitx(view, mbuilder, catalog, toolcontext.opt_no_color.value)
+var q = toolcontext.opt_command.value
+if q != null then # shortcut prompt
+       print ""
+       nitx.do_command(q)
+       return
+end
+nitx.start