doc/commands: introduce catalog commands
[nit.git] / src / doc / commands / commands_catalog.nit
1 # This file is part of NIT ( http://www.nitlanguage.org ).
2 #
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
6 #
7 # http://www.apache.org/licenses/LICENSE-2.0
8 #
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.
14
15 # Commands to retrieve Catalog related data
16 module commands_catalog
17
18 import commands_model
19
20 # A DocCommand based on a Catalog
21 abstract class CmdCatalog
22 super DocCommand
23
24 # Catalog to query at
25 var catalog: Catalog
26 end
27
28 # A CmdSearch command using a Catalog
29 class CmdCatalogSearch
30 super CmdCatalog
31 super CmdSearch
32
33 autoinit(view, catalog, query, limit, page, count, max)
34
35 redef fun init_results do
36 if results != null then return new CmdSuccess
37
38 var res = super
39 if not res isa CmdSuccess then return res
40
41 var query = self.query
42 if query == null then return new ErrorNoQuery
43 sorter = null
44
45 var index = view.index
46
47 # lookup by name prefix
48 var matches = index.find_by_name_prefix(query).uniq.
49 sort(lname_sorter, name_sorter, kind_sorter)
50 matches = matches.rerank.sort(vis_sorter, score_sorter)
51
52 # lookup by tags
53 var malus = matches.length
54 if catalog.tag2proj.has_key(query) then
55 for mpackage in catalog.tag2proj[query] do
56 matches.add new IndexMatch(mpackage, malus)
57 malus += 1
58 end
59 matches = matches.uniq.rerank.sort(vis_sorter, score_sorter)
60 end
61
62 # lookup by full_name prefix
63 malus = matches.length
64 var full_matches = new IndexMatches
65 for match in index.find_by_full_name_prefix(query).
66 sort(lfname_sorter, fname_sorter) do
67 match.score += 1
68 full_matches.add match
69 end
70 matches = matches.uniq
71
72 # lookup by similarity
73 malus = matches.length
74 var sim_matches = new IndexMatches
75 for match in index.find_by_similarity(query).sort(score_sorter, lname_sorter, name_sorter) do
76 if match.score > query.length then break
77 match.score += 1
78 sim_matches.add match
79 end
80 matches.add_all sim_matches
81 matches = matches.uniq
82 results = matches.rerank.sort(vis_sorter, score_sorter).mentities
83 return res
84 end
85
86 private var score_sorter = new ScoreComparator
87 private var vis_sorter = new VisibilityComparator
88 private var name_sorter = new NameComparator
89 private var lname_sorter = new NameLengthComparator
90 private var fname_sorter = new FullNameComparator
91 private var lfname_sorter = new FullNameLengthComparator
92 private var kind_sorter = new MEntityComparator
93 end
94
95 # Retrieve the catalog metadata for a MPackage
96 class CmdMetadata
97 super CmdEntity
98
99 # MPackage metadata retrieved
100 var metadata: nullable MPackageMetadata = null is optional, writable
101
102 redef fun init_command do
103 if metadata != null then return new CmdSuccess
104
105 var res = super
106 if not res isa CmdSuccess then return res
107 var mentity = self.mentity.as(not null)
108
109 if mentity isa MPackage then
110 metadata = mentity.metadata
111 else
112 return new WarningNoMetadata(mentity)
113 end
114 return res
115 end
116 end
117
118 # No metadata for `mentity`
119 class WarningNoMetadata
120 super CmdWarning
121
122 # MEntity provided
123 var mentity: MEntity
124
125 redef fun to_s do return "No metadata for `{mentity.full_name}`"
126 end
127
128 # Retrieve the packages in the catalog
129 class CmdCatalogPackages
130 super CmdCatalog
131 super CmdEntities
132
133 autoinit(view, catalog, limit, page, count, max)
134
135 redef var sorter = new CatalogScoreSorter(catalog) is lazy
136
137 redef fun init_results do
138 if results != null then return new CmdSuccess
139
140 var res = super
141 if not res isa CmdSuccess then return res
142
143 results = catalog.mpackages.values.to_a
144 return res
145 end
146 end
147
148 # Retrieve the catalog stats
149 class CmdCatalogStats
150 super CmdCatalog
151
152 # Retrieved catalog statistics
153 var stats: nullable CatalogStats = null is optional, writable
154
155 redef fun init_command do
156 super
157 self.stats = catalog.catalog_stats
158 return new CmdSuccess
159 end
160 end
161
162 # Retrieve the catalog tags list
163 class CmdCatalogTags
164 super CmdCatalog
165
166 # Sorter to sort tags alphabetically
167 var tags_sorter = new CatalogTagsSorter is optional, writable
168
169 # Count of packages by tag
170 var packages_count_by_tags: nullable ArrayMap[String, Int] = null is optional, writable
171
172 redef fun init_command do
173 super
174 var tags_to_projects = new ArrayMap[String, Int]
175 var tags = catalog.tag2proj.keys.to_a
176 tags_sorter.sort(tags)
177 for tag in tags do
178 if not catalog.tag2proj.has_key(tag) then continue
179 tags_to_projects[tag] = catalog.tag2proj[tag].length
180 end
181 packages_count_by_tags = tags_to_projects
182 return new CmdSuccess
183 end
184 end
185
186 # Retrieve the packages for a tag
187 class CmdCatalogTag
188 super CmdCatalogPackages
189
190 autoinit(view, catalog, tag, limit, page, count, max)
191
192 # The tag to retrieve
193 var tag: nullable String = null is optional, writable
194
195 redef fun init_command do
196 var tag = self.tag
197 if tag == null then return new ErrorNoTag
198
199 if not catalog.tag2proj.has_key(tag) then return new ErrorTagNotFound(tag)
200 return super
201 end
202
203 redef fun init_results do
204 if results != null then return new CmdSuccess
205
206 var res = super
207 if not res isa CmdSuccess then return res
208
209 results = catalog.tag2proj[tag].to_a
210 return res
211 end
212 end
213
214 # No tag name provided
215 class ErrorNoTag
216 super CmdError
217
218 redef fun to_s do return "No tag name provided"
219 end
220
221 # No tag with this name in the catalog
222 class ErrorTagNotFound
223 super CmdError
224
225 # The tag that was not found
226 var tag: String
227
228 redef fun to_s do return "No tag found for `{tag}`"
229 end
230
231 # Retrieve a person from the catalog
232 class CmdCatalogPerson
233 super CmdCatalog
234
235 # Person to retrieve
236 #
237 # You can also pass a `person_name`.
238 var person: nullable Person = null is optional, writable
239
240 # Name of the person to retrieve
241 #
242 # You can also pass a `person` instance.
243 var person_name: nullable String = null is optional, writable
244
245 # Initialize the `person` result
246 fun init_person: CmdMessage do
247 var person = self.person
248 if person != null then
249 person_name = person.name
250 return new CmdSuccess
251 end
252
253 var name = self.person_name
254 if name == null then return new ErrorNoPerson
255 if not catalog.name2person.has_key(name) then return new ErrorPersonNotFound(name)
256 self.person = catalog.name2person[name]
257 return new CmdSuccess
258 end
259
260 redef fun init_command do
261 init_person
262 return super
263 end
264 end
265
266 # No person instance or name provided
267 class ErrorNoPerson
268 super CmdError
269
270 redef fun to_s do return "No person provided"
271 end
272
273 # No person found with this name
274 class ErrorPersonNotFound
275 super CmdError
276
277 # Name of the person that was not found
278 var name: String
279
280 redef fun to_s do return "No person found for `{name}`"
281 end
282
283 # Retrieve the packages maintained by a person
284 class CmdCatalogMaintaining
285 super CmdCatalogPerson
286 super CmdCatalogPackages
287
288 autoinit(view, catalog, person, person_name, limit, page, count, max)
289
290 redef fun init_command do return super
291
292 redef fun init_results do
293 if results != null then return new CmdSuccess
294 var res = super
295 if not res isa CmdSuccess then return res
296 var person = self.person.as(not null)
297
298 if not catalog.maint2proj.has_key(person) then return res
299 results = catalog.maint2proj[person]
300 return res
301 end
302 end
303
304 # Retrieve the packages contributed by a person
305 class CmdCatalogContributing
306 super CmdCatalogPerson
307 super CmdCatalogPackages
308
309 autoinit(view, catalog, person, person_name, limit, page, count, max)
310
311 # Include maintained packages?
312 #
313 # Default is `false`.
314 var maintaining = false is optional, writable
315
316 # FIXME linearization
317 redef fun init_command do return super
318
319 redef fun init_results do
320 if results != null then return new CmdSuccess
321
322 var res = super
323 if not res isa CmdSuccess then return res
324 var person = self.person.as(not null)
325
326 if not catalog.contrib2proj.has_key(person) then return res
327
328 var maint2proj = null
329 if catalog.maint2proj.has_key(person) then
330 maint2proj = catalog.maint2proj[person]
331 end
332
333 var results = new Array[MPackage]
334 for mpackage in catalog.contrib2proj[person] do
335 if not maintaining and maint2proj != null and maint2proj.has(mpackage) then continue
336 results.add mpackage
337 end
338 self.results = results
339 return res
340 end
341 end