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 # Nitx related components
17 # This module is a place holder for `nitx` related services.
18 # No `doc_phase` can be found here, only components used by Nitx tool.
22 import doc
::console_templates
24 # Nitx handles console I/O.
26 # Using `prompt`, the command line can be turned on an interactive tool.
29 # ToolContext used to access options.
32 # DocModel that contains the informations to display.
35 # Comparator used to sort MEntities.
36 var sorter
= new MEntityNameSorter
38 # Displays the welcome message and start prompt.
44 # Displays the welcome message and the list of loaded modules.
46 print
"Welcome in the Nit Index."
48 print
"Loaded modules:"
49 var mmodules
= doc
.mmodules
.to_a
58 # Displays the list of available commands.
61 print
"\tname\t\tlookup module, class and property with the corresponding 'name'"
62 print
"\tdoc: <name::space>\tdisplay the documentation page of 'namespace'"
63 print
"\t:h\t\tdisplay this help message"
64 print
"\t:q\t\tquit interactive mode"
68 # Prompts the user for a command.
71 do_query
(sys
.stdin
.read_line
)
75 # Processes the query string and performs it.
76 fun do_query
(str
: String) do
77 var query
= parse_query
(str
)
78 var res
= query
.perform
(self, doc
)
79 var page
= query
.make_results
(self, res
)
80 print page
.write_to_string
83 # Returns an `NitxQuery` from a raw query string.
84 fun parse_query
(str
: String): NitxQuery do
85 var query
= new NitxQuery(str
)
86 if query
isa NitxCommand then
93 # A query performed on Nitx.
95 # Queries are responsible to collect matching results and render them as a
98 # Used as a factory to concrete instances.
101 # Original query string.
102 fun query_string
: String is abstract
106 # Will return a concrete instance of NitxQuery.
107 new(query_string
: String) do
108 if query_string
== ":q" then
110 else if query_string
== ":h" then
112 else if query_string
.has_prefix
("comment:") then
113 return new CommentQuery(query_string
)
114 else if query_string
.has_prefix
("doc:") then
115 return new DocQuery(query_string
)
117 return new CommentQuery("comment: {query_string}")
120 # Looks up the `doc` model and returns possible matches.
121 fun perform
(nitx
: Nitx, doc
: DocModel): Array[NitxMatch] is abstract
123 # Pretty prints the results for the console.
124 fun make_results
(nitx
: Nitx, results
: Array[NitxMatch]): DocPage do
125 var page
= new DocPage("Results")
126 page
.root
.add_child
(new QueryResultArticle(self, results
))
130 redef fun to_s
do return query_string
133 # Something that matches a `NitxQuery`.
134 abstract class NitxMatch
136 # Query matched by `self`.
139 # Pretty prints `self` for console.
140 fun make_list_item
: String is abstract
143 # A query that contains a meta command.
145 # In Nitx, commands are written such as `command: args...`.
146 abstract class MetaQuery
149 redef var query_string
152 var command
: String is noinit
154 # Arguments passed to the `command`.
155 var args
= new Array[String]
159 var str
= new FlatBuffer
161 while i
< query_string
.length
do
162 var c
= query_string
[i
]
164 if c
== ':' then break
167 command
= str
.write_to_string
169 args
.add query_string
.substring_from
(i
).trim
173 # A match between a `NitxQuery` and a `MEntity`.
180 redef fun make_list_item
do return mentity
.cs_list_item
183 # A query to search a `MEntity` comment by its name or namespace.
187 redef fun perform
(nitx
, doc
) do
188 var name
= args
.first
189 var res
= new Array[NitxMatch]
190 for mentity
in doc
.search_mentities
(name
) do
191 res
.add
new MEntityMatch(self, mentity
)
196 redef fun make_results
(nitx
, results
) do
197 var len
= results
.length
199 var res
= results
.first
.as(MEntityMatch)
200 var mentity
= res
.mentity
201 var page
= new DocPage("Results")
202 var article
= new DefinitionArticle(mentity
)
203 article
.cs_title
= mentity
.name
204 article
.cs_subtitle
= mentity
.cs_declaration
205 page
.root
.add_child article
213 # A query to search a Nitdoc documentation page by its name.
217 redef fun perform
(nitx
, doc
) do
218 var res
= new Array[NitxMatch]
219 var name
= args
.first
220 for page
in doc
.pages
do
221 if name
== "*" then # FIXME dev only
222 res
.add
new PageMatch(self, page
)
223 else if page
.title
== name
then
224 res
.add
new PageMatch(self, page
)
225 else if page
isa MEntityPage and page
.mentity
.cs_namespace
== name
then
226 res
.add
new PageMatch(self, page
)
232 redef fun make_results
(nitx
, results
) do
233 var len
= results
.length
234 # FIXME how to render the pager for one worded namespaces like "standard"?
236 var page
= results
.first
.as(PageMatch).page
237 var pager
= new Pager
238 pager
.add page
.write_to_string
247 # A match between a `DocPage` and a `MEntity`.
254 redef fun make_list_item
do
256 if page
isa MEntityPage then
257 return page
.mentity
.cs_list_item
259 return " * {page.title}"
263 # A query that contains a nitx command.
265 # These commands are prefixed with `:` and are used to control the execution of
266 # `nitx` like displaying the help or quiting.
267 interface NitxCommand
270 # Executes the command.
271 fun execute
(nitx
: Nitx) is abstract
278 redef fun execute
(nitx
) do exit
0
281 # Displays the help message.
285 redef fun execute
(nitx
) do nitx
.help
292 # Lists all MEntities in the model.
293 private var mentities
: Collection[MEntity] is lazy
do
294 var res
= new HashSet[MEntity]
295 res
.add_all mprojects
299 res
.add_all mclassdefs
300 res
.add_all mproperties
301 res
.add_all mpropdefs
305 # Search MEntities that match `name` by their name or namespace.
306 private fun search_mentities
(name
: String): Array[MEntity] do
307 var res
= new Array[MEntity]
308 for mentity
in mentities
do
309 if mentity
.name
!= name
and mentity
.cs_namespace
!= name
then continue
318 # A `DocArticle` that displays query results.
319 private class QueryResultArticle
322 # Query linked to the results to display.
325 # Results to display.
326 var results
: Array[NitxMatch]
328 redef fun render_title
do
329 var len
= results
.length
331 add
"No result found for '{query.query_string}'..."
333 add
"# {len} result(s) for '{query.query_string}'".green
.bold
337 redef fun render_body
do
339 for result
in results
do
341 addn result
.make_list_item
346 # A Pager is used to display data into a unix `less` container.
349 # Content to display.
350 var content
= new FlatBuffer
352 # Adds text to the pager.
353 fun add
(text
: String) do
354 content
.append
(escape
(text
))
357 fun render
do sys
.system
("echo \"{content}\
" | less -r")
359 fun escape
(str
: String): String
361 var b
= new FlatBuffer
362 for c
in str
.chars
do
365 else if c
== '\0' then
367 else if c
== '"' then
369 else if c == '\\' then
371 else if c == '`' then
373 else if c.ascii < 32 then
374 b.append("\\{c.ascii.to_base(8, false)}")