1 # This file is part of NIT ( http://www.nitlanguage.org ).
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
7 # http://www.apache.org/licenses/LICENSE-2.0
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
15 # nit index, is a command tool used to display documentation
19 import modelize_property
22 # Main class of the nit index tool
23 # NitIndex build the model using the toolcontext argument
24 # then wait for query on std in to display documentation
26 private var toolcontext
: ToolContext
27 private var model
: Model
28 private var mbuilder
: ModelBuilder
29 private var mainmodule
: MModule
30 private var arguments
: Array[String]
31 private var renderer
: PagerMatchesRenderer
33 # New constructor to use the pre-calculated model when interpreting a module
34 init with_infos
(mbuilder
: ModelBuilder, mmodule
: MModule) do
36 self.model
= mbuilder
.model
37 self.mbuilder
= mbuilder
39 self.mainmodule
= mmodule
40 self.toolcontext
= mbuilder
.toolcontext
41 self.arguments
= toolcontext
.option_context
.rest
43 renderer
= new PagerMatchesRenderer(self)
46 init(toolcontext
: ToolContext) do
47 # We need a model to collect stufs
48 self.toolcontext
= toolcontext
49 self.toolcontext
.option_context
.options
.clear
50 self.arguments
= toolcontext
.option_context
.rest
52 if arguments
.is_empty
or arguments
.length
> 2 then
53 print
"usage: ni path/to/module.nit [expression]"
54 toolcontext
.option_context
.usage
59 mbuilder
= new ModelBuilder(model
, toolcontext
)
61 # Here we load an process std modules
62 #var dir = "NIT_DIR".environ
63 #var mmodules = modelbuilder.parse_and_build(["{dir}/lib/standard/standard.nit"])
64 var mmodules
= mbuilder
.parse
([arguments
.first
])
65 if mmodules
.is_empty
then return
67 assert mmodules
.length
== 1
68 self.mainmodule
= mmodules
.first
70 renderer
= new PagerMatchesRenderer(self)
74 if arguments
.length
== 1 then
83 print
"Welcome in the Nit Index."
85 print
"Loaded modules:"
86 var mmodules
= new Array[MModule]
87 mmodules
.add_all
(model
.mmodules
)
88 var sorter
= new MModuleNameSorter
99 print
"\tname\t\tlookup module, class and property with the corresponding 'name'"
100 print
"\tparam: Type\tlookup methods using the corresponding 'Type' as parameter"
101 print
"\treturn: Type\tlookup methods returning the corresponding 'Type'"
102 print
"\tnew: Type\tlookup methods creating new instances of 'Type'"
103 print
"\t:h\t\tdisplay this help message"
110 search
(stdin
.read_line
)
113 fun search
(entry
: String) do
114 if entry
.is_empty
then
118 if entry
== ":h" then
123 if entry
== ":q" then return
126 var query
= parse_query
(entry
)
129 var matches
= new HashSet[IndexMatch]
130 if query
isa IndexQueryPair then
131 if query
.category
== "return" then
133 matches
.add_all
(search_returns
(query
))
134 else if query
.category
== "param" then
136 matches
.add_all
(search_params
(query
))
137 else if query
.category
== "new" then
139 matches
.add_all
(search_inits
(query
))
142 matches
.add_all
(search_modules
(query
))
143 matches
.add_all
(search_classes
(query
))
144 matches
.add_all
(search_properties
(query
))
147 if matches
.is_empty
then
148 print
"Nothing known about '{query.string}', type ':h' for help"
150 renderer
.render_matches
(query
, matches
)
152 if arguments
.length
== 1 then prompt
155 private fun parse_query
(str
: String): IndexQuery do
156 var parts
= str
.split_with
(":")
157 if parts
.length
== 1 then
158 return new IndexQuery(str
, parts
[0])
160 var category
= parts
[0]
161 var keyword
= parts
[1]
162 if keyword
.first
== ' ' then keyword
= keyword
.substring_from
(1)
163 return new IndexQueryPair(str
, keyword
, category
)
168 private fun search_modules
(query
: IndexQuery): Set[MModule] do
169 var matches
= new HashSet[MModule]
170 for mmodule
in model
.mmodules
do
171 if mmodule
.name
== query
.keyword
then matches
.add
(mmodule
)
177 private fun search_classes
(query
: IndexQuery): Set[MClass] do
178 var matches
= new HashSet[MClass]
179 for mclass
in model
.mclasses
do
180 if mclass
.name
== query
.keyword
then matches
.add
(mclass
)
185 # search for properties
186 private fun search_properties
(query
: IndexQuery): Set[MProperty] do
187 var matches
= new HashSet[MProperty]
188 for mproperty
in model
.mproperties
do
189 if mproperty
.name
== query
.keyword
then matches
.add
(mproperty
)
194 # search for mpropdef returning keyword
195 private fun search_returns
(query
: IndexQuery): Set[MProperty] do
196 var matches
= new HashSet[MProperty]
197 for mproperty
in model
.mproperties
do
198 var intro
= mproperty
.intro
199 if intro
isa MMethodDef then
200 if intro
.msignature
.return_mtype
!= null and intro
.msignature
.return_mtype
.to_console
.has_prefix
(query
.keyword
) then matches
.add
(mproperty
)
201 else if intro
isa MAttributeDef then
202 if intro
.static_mtype
.to_console
.has_prefix
(query
.keyword
) then matches
.add
(mproperty
)
208 # search for mpropdef taking keyword as parameter
209 private fun search_params
(query
: IndexQuery): Set[MProperty] do
210 var matches
= new HashSet[MProperty]
211 for mproperty
in model
.mproperties
do
212 var intro
= mproperty
.intro
213 if intro
isa MMethodDef then
214 var mparameters
= intro
.msignature
.mparameters
215 for mparameter
in mparameters
do
216 if mparameter
.mtype
.to_console
.has_prefix
(query
.keyword
) then matches
.add
(mproperty
)
218 else if intro
isa MAttributeDef then
219 if intro
.static_mtype
.to_console
.has_prefix
(query
.keyword
) then matches
.add
(mproperty
)
225 # search for mpropdef creating new instance of keyword
226 private fun search_inits
(query
: IndexQuery): Set[MPropDef] do
227 var mtype2mpropdefs
= toolcontext
.nitx_phase
.mtype2mpropdefs
228 var matches
= new HashSet[MPropDef]
229 for mtype
in mtype2mpropdefs
.keys
do
230 if mtype
.to_console
.has_prefix
(query
.keyword
) then
231 for mpropdef
in mtype2mpropdefs
[mtype
] do
232 matches
.add
(mpropdef
)
240 private class IndexQuery
243 init(string
: String, keyword
: String) do
245 self.keyword
= keyword
249 private class IndexQueryPair
252 init(string
: String, keyword
: String, category
: String) do
253 super(string
, keyword
)
254 self.category
= category
258 # A match to a query in the nit index
259 private interface IndexMatch
260 # Short preview of the result for result list display
261 fun preview
(index
: NitIndex, output
: Pager) is abstract
262 fun content
(index
: NitIndex, output
: Pager) is abstract
267 redef class ToolContext
268 private var nitx_phase
: NitxPhase = new NitxPhase(self, [typing_phase
])
271 # Compiler phase for nitx
272 private class NitxPhase
275 var mtype2mpropdefs
= new HashMap[MType, Set[MPropDef]]
276 redef fun process_npropdef
(npropdef
) do
277 var visitor
= new TypeInitVisitor
278 visitor
.enter_visit
(npropdef
)
279 for mtype
in visitor
.inits
do
280 if not mtype2mpropdefs
.has_key
(mtype
) then
281 mtype2mpropdefs
[mtype
] = new HashSet[MPropDef]
283 mtype2mpropdefs
[mtype
].add
(npropdef
.mpropdef
.as(not null))
288 # Visitor looking for initialized mtype (new T)
289 private class TypeInitVisitor
292 var inits
= new HashSet[MType]
293 redef fun visit
(node
)
297 if not node
isa ANewExpr then return
298 var mtype
= node
.n_type
.mtype
299 if mtype
!= null then inits
.add
(mtype
)
303 # Pager output for console
305 private class PagerMatchesRenderer
307 init(index
: NitIndex) do self.index
= index
309 fun render_matches
(query
: IndexQuery, matches
: Collection[IndexMatch]) do
310 var pager
= new Pager
311 if matches
.length
== 1 then
312 pager
.add
("= result for '{query.string}'".bold
)
314 pager
.indent
= pager
.indent
+ 1
315 matches
.first
.content
(index
, pager
)
316 pager
.indent
= pager
.indent
- 1
318 pager
.add
("= multiple results for '{query.string}'".bold
)
319 pager
.indent
= pager
.indent
+ 1
320 for match
in matches
do
322 match
.preview
(index
, pager
)
324 pager
.indent
= pager
.indent
- 1
329 private fun props_fulldoc
(pager
: Pager, raw_mprops
: List[MProperty]) do
331 var cats
= new HashMap[MModule, Array[MProperty]]
332 for mprop
in raw_mprops
do
333 if mprop
isa MAttribute then continue
334 var key
= mprop
.intro
.mclassdef
.mmodule
335 if not cats
.has_key
(key
) then cats
[key
] = new Array[MProperty]
339 var sorter
= new MModuleNameSorter
340 var sorted
= new Array[MModule]
341 sorted
.add_all
(cats
.keys
)
344 for mmodule
in sorted
do
345 var mprops
= cats
[mmodule
]
346 pager
.add
("# matches in module {mmodule.namespace.bold}")
347 var sorterp
= new MPropertyNameSorter
349 for mprop
in mprops
do
358 var content
= new Buffer
360 fun add
(text
: String) do
364 fun add_indent
do addn
(" " * indent
)
365 fun addn
(text
: String) do content
.append
(text
.escape
)
366 fun add_rule
do add
("\n---\n")
367 fun render
do sys
.system
("echo \"{content}\
" | pager -r")
372 # prototype of the module
373 # module ownername::name
374 private fun prototype
: String do return "module {name.bold}"
376 # namespace of the module
378 private fun namespace
: String do
379 if public_owner
== null then
382 return "{public_owner.namespace}::{self.name}"
386 redef fun preview
(index
, pager
) do
387 if index
.mbuilder
.mmodule2nmodule
.has_key
(self) then
388 var node
= index
.mbuilder
.mmodule2nmodule
[self]
389 if node
.n_moduledecl
!= null and not node
.n_moduledecl
.n_doc
== null and not node
.n_moduledecl
.n_doc
.short_comment
.is_empty
then
390 pager
.add
(node
.n_moduledecl
.n_doc
.short_comment
.green
)
394 pager
.add
("{namespace}".bold
.gray
+ " (lines {location.lines})".gray
)
397 redef fun content
(index
, pager
) do
398 if index
.mbuilder
.mmodule2nmodule
.has_key
(self) then
399 var node
= index
.mbuilder
.mmodule2nmodule
[self]
400 if node
.n_moduledecl
!= null and not node
.n_moduledecl
.n_doc
== null and not node
.n_moduledecl
.n_doc
.comment
.is_empty
then
401 for comment
in node
.n_moduledecl
.n_doc
.comment
do pager
.add
(comment
.green
)
405 pager
.add
("{namespace}".bold
.gray
+ " (lines {location.lines})".gray
)
406 pager
.indent
= pager
.indent
+ 1
407 var sorter
= new MModuleNameSorter
409 var imports
= new Array[MModule]
410 for mmodule
in in_importation
.direct_greaters
.to_a
do
411 if not in_nesting
.direct_greaters
.has
(mmodule
) then imports
.add
(mmodule
)
413 if not imports
.is_empty
then
416 pager
.add
("== imported modules".bold
)
417 pager
.indent
= pager
.indent
+ 1
418 for mmodule
in imports
do
420 mmodule
.preview
(index
, pager
)
422 pager
.indent
= pager
.indent
- 1
425 var nested
= in_nesting
.direct_greaters
.to_a
426 if not nested
.is_empty
then
429 pager
.add
("== nested modules".bold
)
430 pager
.indent
= pager
.indent
+ 1
431 for mmodule
in nested
do
433 mmodule
.preview
(index
, pager
)
435 pager
.indent
= pager
.indent
- 1
438 var csorter
= new MClassDefNameSorter
439 var intros
= new Array[MClassDef]
440 var redefs
= new Array[MClassDef]
441 for mclassdef
in mclassdefs
do
442 if mclassdef
.is_intro
then
443 intros
.add
(mclassdef
)
445 redefs
.add
(mclassdef
)
449 if not intros
.is_empty
then
452 pager
.add
("== introduced classes".bold
)
453 pager
.indent
= pager
.indent
+ 1
454 for mclass
in intros
do
456 mclass
.preview
(index
, pager
)
458 pager
.indent
= pager
.indent
- 1
461 if not redefs
.is_empty
then
464 pager
.add
("== refined classes".bold
)
465 pager
.indent
= pager
.indent
+ 1
466 for mclass
in redefs
do
468 mclass
.preview
(index
, pager
)
470 pager
.indent
= pager
.indent
- 1
472 pager
.indent
= pager
.indent
- 1
478 # return the generic signature of the class
480 private fun signature
: String do
484 for i
in [0..intro
.parameter_names
.length
[ do
485 res
.append
(intro
.parameter_names
[i
])
486 if i
< intro
.parameter_names
.length
- 1 then res
.append
(", ")
493 # return the prototype of the class
494 # class name is displayed with colors depending on visibility
495 # abstract interface Foo[E]
496 private fun prototype
: String do
498 res
.append
("{kind} ")
499 if visibility
.to_s
== "public" then res
.append
("{name}{signature}".bold
.green
)
500 if visibility
.to_s
== "private" then res
.append
("{name}{signature}".bold
.red
)
501 if visibility
.to_s
== "protected" then res
.append
("{name}{signature}".bold
.yellow
)
505 private fun namespace
: String do
506 return "{intro_mmodule.namespace}::{name}"
509 redef fun preview
(index
, pager
) do
510 intro
.preview
(index
, pager
)
513 redef fun content
(index
, pager
) do
515 if index
.mbuilder
.mclassdef2nclassdef
.has_key
(intro
) then
516 var node
= index
.mbuilder
.mclassdef2nclassdef
[intro
]
517 if node
isa AStdClassdef and not node
.n_doc
== null and not node
.n_doc
.comment
.is_empty
then
518 for comment
in node
.n_doc
.comment
do pager
.add
(comment
.green
)
521 pager
.add
(intro
.to_console
)
522 pager
.add
("{intro.namespace}".bold
.gray
+ " (lines {intro.location.lines})".gray
)
523 pager
.indent
= pager
.indent
+ 1
525 var supers
= self.in_hierarchy
(index
.mainmodule
).direct_greaters
.to_a
526 if not supers
.is_empty
then
527 var csorter
= new MClassNameSorter
530 pager
.add
("== supers".bold
)
531 pager
.indent
= pager
.indent
+ 1
532 for mclass
in supers
do
534 mclass
.preview
(index
, pager
)
536 pager
.indent
= pager
.indent
- 1
539 if not self.parameter_types
.is_empty
then
541 pager
.add
("== formal types".bold
)
542 pager
.indent
= pager
.indent
+ 1
543 for ft
, bound
in self.parameter_types
do
545 pager
.add
("{ft.to_s.bold.green}: {bound.to_console}")
547 pager
.indent
= pager
.indent
- 1
550 var psorter
= new MPropDefNameSorter
551 var mpropdefs
= intro
.mpropdefs
552 index
.mainmodule
.linearize_mpropdefs
(mpropdefs
)
553 for cat
in intro
.cats2mpropdefs
.keys
do
554 var defs
= intro
.cats2mpropdefs
[cat
].to_a
555 if defs
.is_empty
then continue
558 pager
.add
("== {cat}".bold
)
559 pager
.indent
= pager
.indent
+ 1
560 for mpropdef
in defs
do
562 mpropdef
.preview
(index
, pager
)
564 pager
.indent
= pager
.indent
- 1
567 if not self.mclassdefs
.is_empty
then
569 pager
.add
("== refinements".bold
)
570 var mclassdefs
= self.mclassdefs
571 index
.mainmodule
.linearize_mclassdefs
(mclassdefs
)
572 pager
.indent
= pager
.indent
+ 1
573 for mclassdef
in mclassdefs
do
574 if not mclassdef
.is_intro
then
576 mclassdef
.content
(index
, pager
)
579 pager
.indent
= pager
.indent
- 1
581 pager
.indent
= pager
.indent
- 1
585 redef class MClassDef
588 private fun namespace
: String do
589 return "{mmodule.full_name}::{mclass.name}"
592 fun to_console
: String do
594 if not is_intro
then res
.append
("redef ")
595 res
.append
(mclass
.prototype
)
599 redef fun preview
(index
, pager
) do
600 if index
.mbuilder
.mclassdef2nclassdef
.has_key
(self) then
601 var node
= index
.mbuilder
.mclassdef2nclassdef
[self]
602 if node
isa AStdClassdef and not node
.n_doc
== null and not node
.n_doc
.short_comment
.is_empty
then
603 pager
.add
(node
.n_doc
.short_comment
.green
)
606 pager
.add
(to_console
)
607 pager
.add
("{namespace}".bold
.gray
+ " (lines {location.lines})".gray
)
610 redef fun content
(index
, pager
) do
611 if index
.mbuilder
.mclassdef2nclassdef
.has_key
(self) then
612 var node
= index
.mbuilder
.mclassdef2nclassdef
[self]
613 if node
isa AStdClassdef and not node
.n_doc
== null and not node
.n_doc
.comment
.is_empty
then
614 for comment
in node
.n_doc
.comment
do pager
.add
(comment
.green
)
617 pager
.add
(to_console
)
618 pager
.add
("{namespace}".bold
.gray
+ " (lines {location.lines})".gray
)
619 pager
.indent
= pager
.indent
+ 1
620 var mpropdefs
= self.mpropdefs
621 var psorter
= new MPropDefNameSorter
622 index
.mainmodule
.linearize_mpropdefs
(mpropdefs
)
623 for cat
in cats2mpropdefs
.keys
do
624 var defs
= cats2mpropdefs
[cat
].to_a
626 if defs
.is_empty
then continue
628 pager
.add
("== {cat}".bold
)
629 pager
.indent
= pager
.indent
+ 1
630 for mpropdef
in defs
do
632 mpropdef
.preview
(index
, pager
)
634 pager
.indent
= pager
.indent
- 1
636 pager
.indent
= pager
.indent
- 1
639 # get mpropdefs grouped by categories (vt, init, methods)
640 fun cats2mpropdefs
: Map[String, Set[MPropDef]] do
641 var cats
= new ArrayMap[String, Set[MPropDef]]
642 cats
["virtual types"] = new HashSet[MPropDef]
643 cats
["constructors"] = new HashSet[MPropDef]
644 cats
["methods"] = new HashSet[MPropDef]
646 for mpropdef
in mpropdefs
do
647 if mpropdef
isa MAttributeDef then continue
648 if mpropdef
isa MVirtualTypeDef then cats
["virtual types"].add
(mpropdef
)
649 if mpropdef
isa MMethodDef then
650 if mpropdef
.mproperty
.is_init
then
651 cats
["constructors"].add
(mpropdef
)
653 cats
["methods"].add
(mpropdef
)
661 redef class MProperty
664 fun to_console
: String do
665 if visibility
.to_s
== "public" then return name
.green
666 if visibility
.to_s
== "private" then return name
.red
667 if visibility
.to_s
== "protected" then return name
.yellow
671 redef fun preview
(index
, pager
) do
672 intro
.preview
(index
, pager
)
675 redef fun content
(index
, pager
) do
676 intro
.content
(index
, pager
)
677 pager
.indent
= pager
.indent
+ 1
678 var mpropdefs
= self.mpropdefs
679 index
.mainmodule
.linearize_mpropdefs
(mpropdefs
)
680 for mpropdef
in mpropdefs
do
681 if mpropdef
isa MAttributeDef then continue
682 if not mpropdef
.is_intro
then
684 mpropdef
.preview
(index
, pager
)
687 pager
.indent
= pager
.indent
- 1
694 fun to_console
: String is abstract
696 private fun namespace
: String do
697 return "{mclassdef.namespace}::{mproperty.name}"
700 redef fun preview
(index
, pager
) do
701 if index
.mbuilder
.mpropdef2npropdef
.has_key
(self) then
702 var nprop
= index
.mbuilder
.mpropdef2npropdef
[self]
703 if not nprop
.n_doc
== null and not nprop
.n_doc
.short_comment
.is_empty
then
704 pager
.add
(nprop
.n_doc
.short_comment
.green
)
707 pager
.add
(to_console
)
708 pager
.add
("{namespace}".bold
.gray
+ " (lines {location.lines})".gray
)
711 redef fun content
(index
, pager
) do
712 if index
.mbuilder
.mpropdef2npropdef
.has_key
(self) then
713 var nprop
= index
.mbuilder
.mpropdef2npropdef
[self]
714 if not nprop
.n_doc
== null and not nprop
.n_doc
.comment
.is_empty
then
715 for comment
in nprop
.n_doc
.comment
do pager
.add
(comment
.green
)
718 pager
.add
(to_console
)
719 pager
.add
("{namespace}".bold
.gray
+ " (lines {location.lines})".gray
)
723 redef class MMethodDef
724 redef fun to_console
do
726 if not is_intro
then res
.append
("redef ")
727 if not mproperty
.is_init
then res
.append
("fun ")
728 res
.append
(mproperty
.to_console
.bold
)
729 if msignature
!= null then res
.append
(msignature
.to_console
)
730 # FIXME: modifiers should be accessible via the model
731 #if self isa ADeferredMethPropdef then ret = "{ret} is abstract"
732 #if self isa AInternMethPropdef then ret = "{ret} is intern"
733 #if self isa AExternMethPropdef then ret = "{ret} is extern"
738 redef class MVirtualTypeDef
739 redef fun to_console
do
742 res
.append
(mproperty
.to_console
.bold
)
743 res
.append
(": {bound.to_console}")
748 redef class MAttributeDef
749 redef fun to_console
do
752 res
.append
(mproperty
.to_console
.bold
)
753 res
.append
(": {static_mtype.to_console}")
758 redef class MSignature
759 redef fun to_console
do
761 if not mparameters
.is_empty
then
763 for i
in [0..mparameters
.length
[ do
764 res
.append
(mparameters
[i
].to_console
)
765 if i
< mparameters
.length
- 1 then res
.append
(", ")
769 if return_mtype
!= null then
770 res
.append
(": {return_mtype.to_console}")
776 redef class MParameter
777 fun to_console
: String do
779 res
.append
("{name}: {mtype.to_console}")
780 if is_vararg
then res
.append
("...")
786 fun to_console
: String do return self.to_s
789 redef class MNullableType
790 redef fun to_console
do return "nullable {mtype.to_console}"
793 redef class MGenericType
794 redef fun to_console
do
796 res
.append
("{mclass.name}[")
797 for i
in [0..arguments
.length
[ do
798 res
.append
(arguments
[i
].to_console
)
799 if i
< arguments
.length
- 1 then res
.append
(", ")
806 redef class MParameterType
807 redef fun to_console
do return mclass
.intro
.parameter_names
[rank
]
810 redef class MVirtualType
811 redef fun to_console
do return mproperty
.name
815 private fun comment
: List[String] do
816 var res
= new List[String]
817 for t
in n_comment
do
818 res
.add
(t
.text
.replace
("\n", ""))
823 private fun short_comment
: String do
824 return n_comment
.first
.text
.replace
("\n", "")
828 redef class AAttrPropdef
829 private fun read_accessor
: String do
831 #FIXME bug with standard::stream::FDStream::fd
832 var name
= mreadpropdef
.mproperty
.name
833 if mpropdef
.mproperty
.visibility
.to_s
== "public" then ret
= "{ret}{name.green}"
834 if mpropdef
.mproperty
.visibility
.to_s
== "private" then ret
= "{ret}{name.red}"
835 if mpropdef
.mproperty
.visibility
.to_s
== "protected" then ret
= "{ret}{name.yellow}"
836 ret
= "{ret}: {n_type.to_s}"
837 if n_kwredef
!= null then ret
= "redef {ret}"
841 private fun write_accessor
: String do
843 var name
= "{mreadpropdef.mproperty.name}="
844 if n_readable
!= null and n_readable
.n_visibility
!= null then
845 if n_readable
.n_visibility
isa APublicVisibility then ret
= "{ret}{name.green}"
846 if n_readable
.n_visibility
isa APrivateVisibility then ret
= "{ret}{name.red}"
847 if n_readable
.n_visibility
isa AProtectedVisibility then ret
= "{ret}{name.yellow}"
849 ret
= "{ret}{name.red}"
851 ret
= "{ret}({mreadpropdef.mproperty.name}: {n_type.to_s})"
852 if n_kwredef
!= null then ret
= "redef {ret}"
857 # Redef String class to add a function to color the string
860 private fun add_escape_char
(escapechar
: String): String do
861 return "{escapechar}{self}\\033[0m"
864 private fun esc
: Char do return 27.ascii
865 private fun gray
: String do return add_escape_char
("{esc}[30m")
866 private fun red
: String do return add_escape_char
("{esc}[31m")
867 private fun green
: String do return add_escape_char
("{esc}[32m")
868 private fun yellow
: String do return add_escape_char
("{esc}[33m")
869 private fun blue
: String do return add_escape_char
("{esc}[34m")
870 private fun purple
: String do return add_escape_char
("{esc}[35m")
871 private fun cyan
: String do return add_escape_char
("{esc}[36m")
872 private fun light_gray
: String do return add_escape_char
("{esc}[37m")
873 private fun bold
: String do return add_escape_char
("{esc}[1m")
874 private fun underline
: String do return add_escape_char
("{esc}[4m")
876 private fun escape
: String
882 else if c
== '\0' then
884 else if c
== '"' then
886 else if c == '\\' then
888 else if c == '`' then
890 else if c.ascii < 32 then
891 b.append("\\{c.ascii.to_base(8, false)}")
902 return "{line_start}-{line_end}"
906 # Create a tool context to handle options and paths
907 var toolcontext = new ToolContext
908 toolcontext.process_options
910 # Here we launch the nit index
911 var ni = new NitIndex(toolcontext)
914 # TODO seek subclasses and super classes <.<class> >.<class>
915 # TODO seek subclasses and super types <:<type> >:<type>
916 # TODO seek with regexp
917 # TODO standardize namespaces with private option