- end
- pager.add_rule
- end
- end
-end
-
-private class Pager
- var content = new Buffer
- var indent = 0
- fun add(text: String) do
- add_indent
- addn("{text}\n")
- end
- fun add_indent do addn(" " * indent)
- fun addn(text: String) do content.append(text.escape)
- fun add_rule do add("\n---\n")
- fun render do sys.system("echo \"{content}\" | pager -r")
-end
-
-redef class MModule
- super IndexMatch
- # prototype of the module
- # module name
- private fun prototype: String do return "module {name.bold}"
-
- # namespace of the module
- # project::name
- private fun namespace: String do
- if mgroup == null or mgroup.mproject.name == self.name then
- return self.name
- else
- return "{mgroup.mproject}::{self.name}"
- end
- end
-
- redef fun preview(index, pager) do
- var mdoc = self.mdoc
- if mdoc != null then
- pager.add(mdoc.short_comment.green)
- end
- pager.add(prototype)
- pager.add("{namespace}".bold.gray + " (lines {location.lines})".gray)
- end
-
- redef fun content(index, pager) do
- var mdoc = self.mdoc
- if mdoc != null then
- for comment in mdoc.content do pager.add(comment.green)
- end
- pager.add(prototype)
- pager.add("{namespace}".bold.gray + " (lines {location.lines})".gray)
- pager.indent = pager.indent + 1
- var sorter = new MModuleNameSorter
- # imported modules
- var imports = new Array[MModule]
- for mmodule in in_importation.direct_greaters.to_a do
- imports.add(mmodule)
- end
- if not imports.is_empty then
- sorter.sort(imports)
- pager.add("")
- pager.add("== imported modules".bold)
- pager.indent = pager.indent + 1
- for mmodule in imports do
- pager.add("")
- mmodule.preview(index, pager)
- end
- pager.indent = pager.indent - 1
- end
- # mclassdefs
- var csorter = new MClassDefNameSorter
- var intros = new Array[MClassDef]
- var redefs = new Array[MClassDef]
- for mclassdef in mclassdefs do
- if mclassdef.is_intro then
- intros.add(mclassdef)
- else
- redefs.add(mclassdef)
- end
- end
- # introductions
- if not intros.is_empty then
- csorter.sort(intros)
- pager.add("")
- pager.add("== introduced classes".bold)
- pager.indent = pager.indent + 1
- for mclass in intros do
- pager.add("")
- mclass.preview(index, pager)
- end
- pager.indent = pager.indent - 1
- end
- # refinements
- if not redefs.is_empty then
- csorter.sort(redefs)
- pager.add("")
- pager.add("== refined classes".bold)
- pager.indent = pager.indent + 1
- for mclass in redefs do
- pager.add("")
- mclass.preview(index, pager)
- end
- pager.indent = pager.indent - 1
- end
- pager.indent = pager.indent - 1
- end
-end
-
-redef class MClass
- super IndexMatch
- # return the generic signature of the class
- # [E, F]
- private fun signature: String do
- var res = new Buffer
- if arity > 0 then
- res.append("[")
- for i in [0..intro.parameter_names.length[ do
- res.append(intro.parameter_names[i])
- if i < intro.parameter_names.length - 1 then res.append(", ")
- end
- res.append("]")
- end
- return res.to_s
- end
-
- # return the prototype of the class
- # class name is displayed with colors depending on visibility
- # abstract interface Foo[E]
- private fun prototype: String do
- var res = new Buffer
- res.append("{kind} ")
- if visibility.to_s == "public" then res.append("{name}{signature}".bold.green)
- if visibility.to_s == "private" then res.append("{name}{signature}".bold.red)
- if visibility.to_s == "protected" then res.append("{name}{signature}".bold.yellow)
- return res.to_s
- end
-
- private fun namespace: String do
- return "{intro_mmodule.namespace}::{name}"
- end
-
- redef fun preview(index, pager) do
- intro.preview(index, pager)
- end
-
- redef fun content(index, pager) do
- # intro comment
- var mdoc = intro.mdoc
- if mdoc != null then
- for comment in mdoc.content do pager.add(comment.green)
- end
- pager.add(intro.to_console)
- pager.add("{intro.namespace}".bold.gray + " (lines {intro.location.lines})".gray)
- pager.indent = pager.indent + 1
- # parents
- var supers = self.in_hierarchy(index.mainmodule).direct_greaters.to_a
- if not supers.is_empty then
- var csorter = new MClassNameSorter
- csorter.sort(supers)
- pager.add("")
- pager.add("== supers".bold)
- pager.indent = pager.indent + 1
- for mclass in supers do
- pager.add("")
- mclass.preview(index, pager)
- end
- pager.indent = pager.indent - 1
- end
- # formal types
- if not self.parameter_types.is_empty then
- pager.add("")
- pager.add("== formal types".bold)
- pager.indent = pager.indent + 1
- for ft, bound in self.parameter_types do
- pager.add("")
- pager.add("{ft.to_s.bold.green}: {bound.to_console}")
- end
- pager.indent = pager.indent - 1
- end
- # intro mproperties
- var psorter = new MPropDefNameSorter
- var mpropdefs = intro.mpropdefs
- index.mainmodule.linearize_mpropdefs(mpropdefs)
- for cat in intro.cats2mpropdefs.keys do
- var defs = intro.cats2mpropdefs[cat].to_a
- if defs.is_empty then continue
- psorter.sort(defs)
- pager.add("")
- pager.add("== {cat}".bold)
- pager.indent = pager.indent + 1
- for mpropdef in defs do
- pager.add("")
- mpropdef.preview(index, pager)
- end
- pager.indent = pager.indent - 1
- end
- # refinements
- if not self.mclassdefs.is_empty then
- pager.add("")
- pager.add("== refinements".bold)
- var mclassdefs = self.mclassdefs
- index.mainmodule.linearize_mclassdefs(mclassdefs)
- pager.indent = pager.indent + 1
- for mclassdef in mclassdefs do
- if not mclassdef.is_intro then
- pager.add("")
- mclassdef.content(index, pager)
- end
- end
- pager.indent = pager.indent - 1
- end
- pager.indent = pager.indent - 1
- end
-end
-
-redef class MClassDef
- super IndexMatch
-
- private fun namespace: String do
- return "{mmodule.full_name}::{mclass.name}"
- end
-
- fun to_console: String do
- var res = new Buffer
- if not is_intro then res.append("redef ")
- res.append(mclass.prototype)
- return res.to_s
- end
-
- redef fun preview(index, pager) do
- var mdoc = self.mdoc
- if mdoc != null then
- pager.add(mdoc.short_comment.green)
- end
- pager.add(to_console)
- pager.add("{namespace}".bold.gray + " (lines {location.lines})".gray)
- end
-
- redef fun content(index, pager) do
- var mdoc = self.mdoc
- if mdoc != null then
- for comment in mdoc.content do pager.add(comment.green)
- end
- pager.add(to_console)
- pager.add("{namespace}".bold.gray + " (lines {location.lines})".gray)
- pager.indent = pager.indent + 1
- var mpropdefs = self.mpropdefs
- var psorter = new MPropDefNameSorter
- index.mainmodule.linearize_mpropdefs(mpropdefs)
- for cat in cats2mpropdefs.keys do
- var defs = cats2mpropdefs[cat].to_a
- psorter.sort(defs)
- if defs.is_empty then continue
- pager.add("")
- pager.add("== {cat}".bold)
- pager.indent = pager.indent + 1
- for mpropdef in defs do
- pager.add("")
- mpropdef.preview(index, pager)
- end
- pager.indent = pager.indent - 1
- end
- pager.indent = pager.indent - 1
- end
-
- # get mpropdefs grouped by categories (vt, init, methods)
- fun cats2mpropdefs: Map[String, Set[MPropDef]] do
- var cats = new ArrayMap[String, Set[MPropDef]]
- cats["virtual types"] = new HashSet[MPropDef]
- cats["constructors"] = new HashSet[MPropDef]
- cats["methods"] = new HashSet[MPropDef]
-
- for mpropdef in mpropdefs do
- if mpropdef isa MAttributeDef then continue
- if mpropdef isa MVirtualTypeDef then cats["virtual types"].add(mpropdef)
- if mpropdef isa MMethodDef then
- if mpropdef.mproperty.is_init then
- cats["constructors"].add(mpropdef)
- else
- cats["methods"].add(mpropdef)
- end
- end
- end
- return cats
- end
-end
-
-redef class MProperty
- super IndexMatch
-
- fun to_console: String do
- if visibility.to_s == "public" then return name.green
- if visibility.to_s == "private" then return name.red
- if visibility.to_s == "protected" then return name.yellow
- return name.bold
- end
-
- redef fun preview(index, pager) do
- intro.preview(index, pager)
- end
-
- redef fun content(index, pager) do
- intro.content(index, pager)
- pager.indent = pager.indent + 1
- var mpropdefs = self.mpropdefs
- index.mainmodule.linearize_mpropdefs(mpropdefs)
- for mpropdef in mpropdefs do
- if mpropdef isa MAttributeDef then continue
- if not mpropdef.is_intro then
- pager.add("")
- mpropdef.preview(index, pager)
- end
- end
- pager.indent = pager.indent - 1
- end
-end
-
-redef class MPropDef
- super IndexMatch
-
- fun to_console: String is abstract
-
- private fun namespace: String do
- return "{mclassdef.namespace}::{mproperty.name}"
- end
-
- redef fun preview(index, pager) do
- var mdoc = self.mdoc
- if mdoc != null then
- pager.add(mdoc.short_comment.green)
- end
- pager.add(to_console)
- pager.add("{namespace}".bold.gray + " (lines {location.lines})".gray)
- end
-
- redef fun content(index, pager) do
- var mdoc = self.mdoc
- if mdoc != null then
- for comment in mdoc.content do pager.add(comment.green)
- end
- pager.add(to_console)
- pager.add("{namespace}".bold.gray + " (lines {location.lines})".gray)
- end
-end
-
-redef class MMethodDef
- redef fun to_console do
- var res = new Buffer
- if not is_intro then res.append("redef ")
- if not mproperty.is_init then res.append("fun ")
- res.append(mproperty.to_console.bold)
- if msignature != null then res.append(msignature.to_console)
- # FIXME: modifiers should be accessible via the model
- #if self isa ADeferredMethPropdef then ret = "{ret} is abstract"
- #if self isa AInternMethPropdef then ret = "{ret} is intern"
- #if self isa AExternMethPropdef then ret = "{ret} is extern"
- return res.to_s
- end
-end
-
-redef class MVirtualTypeDef
- redef fun to_console do
- var res = new Buffer
- res.append("type ")
- res.append(mproperty.to_console.bold)
- res.append(": {bound.to_console}")
- return res.to_s
- end
-end
-
-redef class MAttributeDef
- redef fun to_console do
- var res = new Buffer
- res.append("var ")
- res.append(mproperty.to_console.bold)
- res.append(": {static_mtype.to_console}")
- return res.to_s
- end
-end
-
-redef class MSignature
- redef fun to_console do
- var res = new Buffer
- if not mparameters.is_empty then
- res.append("(")
- for i in [0..mparameters.length[ do
- res.append(mparameters[i].to_console)
- if i < mparameters.length - 1 then res.append(", ")
- end
- res.append(")")
- end
- if return_mtype != null then
- res.append(": {return_mtype.to_console}")
- end
- return res.to_s
- end
-end
-
-redef class MParameter
- fun to_console: String do
- var res = new Buffer
- res.append("{name}: {mtype.to_console}")
- if is_vararg then res.append("...")
- return res.to_s
- end
-end
-
-redef class MType
- fun to_console: String do return self.to_s
-end
-
-redef class MNullableType
- redef fun to_console do return "nullable {mtype.to_console}"
-end
-
-redef class MGenericType
- redef fun to_console do
- var res = new Buffer
- res.append("{mclass.name}[")
- for i in [0..arguments.length[ do
- res.append(arguments[i].to_console)
- if i < arguments.length - 1 then res.append(", ")
- end
- res.append("]")
- return res.to_s
- end
-end
-
-redef class MParameterType
- redef fun to_console do return mclass.intro.parameter_names[rank]
-end
-
-redef class MVirtualType
- redef fun to_console do return mproperty.name
-end
-
-redef class MDoc
- private fun short_comment: String do
- return content.first
- end
-end
-
-redef class AAttrPropdef
- private fun read_accessor: String do
- var ret = "fun "
- #FIXME bug with standard::stream::FDStream::fd
- var name = mreadpropdef.mproperty.name
- if mpropdef.mproperty.visibility.to_s == "public" then ret = "{ret}{name.green}"
- if mpropdef.mproperty.visibility.to_s == "private" then ret = "{ret}{name.red}"
- if mpropdef.mproperty.visibility.to_s == "protected" then ret = "{ret}{name.yellow}"
- ret = "{ret}: {n_type.to_s}"
- if n_kwredef != null then ret = "redef {ret}"
- return ret
- end
-
- private fun write_accessor: String do
- var ret = "fun "
- var name = "{mreadpropdef.mproperty.name}="
- if n_readable != null and n_readable.n_visibility != null then
- if n_readable.n_visibility isa APublicVisibility then ret = "{ret}{name.green}"
- if n_readable.n_visibility isa APrivateVisibility then ret = "{ret}{name.red}"
- if n_readable.n_visibility isa AProtectedVisibility then ret = "{ret}{name.yellow}"
- else
- ret = "{ret}{name.red}"
- end
- ret = "{ret}({mreadpropdef.mproperty.name}: {n_type.to_s})"
- if n_kwredef != null then ret = "redef {ret}"
- return ret
- end
-end
-
-# Redef String class to add a function to color the string
-redef class String
-
- private fun add_escape_char(escapechar: String): String do
- return "{escapechar}{self}\\033[0m"
- end
-
- private fun esc: Char do return 27.ascii
- private fun gray: String do return add_escape_char("{esc}[30m")
- private fun red: String do return add_escape_char("{esc}[31m")
- private fun green: String do return add_escape_char("{esc}[32m")
- private fun yellow: String do return add_escape_char("{esc}[33m")
- private fun blue: String do return add_escape_char("{esc}[34m")
- private fun purple: String do return add_escape_char("{esc}[35m")
- private fun cyan: String do return add_escape_char("{esc}[36m")
- private fun light_gray: String do return add_escape_char("{esc}[37m")
- private fun bold: String do return add_escape_char("{esc}[1m")
- private fun underline: String do return add_escape_char("{esc}[4m")
-
- private fun escape: String
- do
- var b = new Buffer
- for c in self.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.ascii < 32 then
- b.append("\\{c.ascii.to_base(8, false)}")
- else
- b.add(c)
- end