Mercurial Hosting > nabble
comparison src/nabble/view/web/template/MacroSourceNamespace.java @ 0:7ecd1a4ef557
add content
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 21 Mar 2019 19:15:52 -0600 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:7ecd1a4ef557 |
---|---|
1 package nabble.view.web.template; | |
2 | |
3 import nabble.model.Site; | |
4 import nabble.modules.ModuleManager; | |
5 import nabble.naml.compiler.Command; | |
6 import nabble.naml.compiler.CommandSpec; | |
7 import nabble.naml.compiler.CompileException; | |
8 import nabble.naml.compiler.IPrintWriter; | |
9 import nabble.naml.compiler.Interpreter; | |
10 import nabble.naml.compiler.JavaCommand; | |
11 import nabble.naml.compiler.Macro; | |
12 import nabble.naml.compiler.Meaning; | |
13 import nabble.naml.compiler.Namespace; | |
14 import nabble.naml.compiler.ParamMeaning; | |
15 import nabble.naml.compiler.Program; | |
16 import nabble.naml.compiler.ScopedInterpreter; | |
17 import nabble.naml.compiler.Source; | |
18 import nabble.naml.compiler.Template; | |
19 import nabble.naml.compiler.Usage; | |
20 import nabble.naml.dom.Attribute; | |
21 import nabble.naml.dom.Container; | |
22 import nabble.naml.dom.Element; | |
23 import nabble.naml.dom.ElementName; | |
24 import nabble.naml.dom.EmptyElement; | |
25 import nabble.naml.dom.Naml; | |
26 import nabble.naml.namespaces.BasicNamespace; | |
27 import nabble.naml.namespaces.CommandDoc; | |
28 import nabble.naml.namespaces.ListSequence; | |
29 import nabble.naml.namespaces.StringList; | |
30 | |
31 import javax.servlet.ServletException; | |
32 import java.io.IOException; | |
33 import java.util.ArrayList; | |
34 import java.util.Arrays; | |
35 import java.util.Collection; | |
36 import java.util.Collections; | |
37 import java.util.Comparator; | |
38 import java.util.HashSet; | |
39 import java.util.List; | |
40 import java.util.Set; | |
41 | |
42 | |
43 @Namespace( | |
44 name = "macro_source", | |
45 global = true | |
46 ) | |
47 public class MacroSourceNamespace extends ServletNamespaceUtils { | |
48 | |
49 private Site site; | |
50 private String[] baseClassArray; | |
51 private String baseClasses; | |
52 private String nextBreadcrumbs; | |
53 private String[] navigationBreadcrumbs; | |
54 private Meaning meaning; | |
55 private String macroOverriddenId; | |
56 private String macroWhichOverridesId; | |
57 | |
58 MacroSourceNamespace(Site site, String id, String base, String breadcrumbs) { | |
59 this.site = site; | |
60 Program program = site.getProgram(); | |
61 meaning = program.getMeaning(id); | |
62 if( meaning == null ) | |
63 throw new NullPointerException("meaning is null for: "+id); | |
64 | |
65 this.baseClasses = base; | |
66 this.baseClassArray = buildBaseClassArray(base); | |
67 this.nextBreadcrumbs = buildNextBreadcrumbs(id, breadcrumbs); | |
68 | |
69 boolean hasBaseClasses = base != null && base.length() > 0; | |
70 if (hasBaseClasses) { | |
71 try { | |
72 Meaning root = program.getMeaning(navigationBreadcrumbs[0]); | |
73 program.getTemplate(root.getName(), this.baseClassArray); | |
74 } catch (CompileException e) { | |
75 throw new RuntimeException(e); | |
76 } | |
77 } | |
78 | |
79 if (meaning instanceof Macro) { | |
80 Macro macro = (Macro) meaning; | |
81 Macro overridden = program.getMacroOverriddenBy(macro); | |
82 this.macroOverriddenId = overridden != null? overridden.getId() : null; | |
83 Macro overrides = program.getMacroWhichOverrides(macro); | |
84 this.macroWhichOverridesId = overrides != null? overrides.getId() : null; | |
85 } | |
86 } | |
87 | |
88 static String[] buildBaseClassArray(String base) { | |
89 boolean hasBaseClasses = base != null && base.length() > 0; | |
90 String[] baseArray = hasBaseClasses? base.split("-") : new String[0]; | |
91 | |
92 String basicNamespace = nabble.naml.namespaces.BasicNamespace.class.getName(); | |
93 String nabbleNamespace = nabble.view.web.template.NabbleNamespace.class.getName(); | |
94 | |
95 if (baseArray.length >=2 && baseArray[0].equals(basicNamespace) && baseArray[1].equals(nabbleNamespace)) { | |
96 return baseArray; | |
97 } else { | |
98 String[] array = new String[baseArray.length+2]; | |
99 array[0] = basicNamespace; | |
100 array[1] = nabbleNamespace; | |
101 | |
102 int i = 2; | |
103 for (String className : baseArray) { | |
104 array[i++] = className; | |
105 } | |
106 return array; | |
107 } | |
108 } | |
109 | |
110 private String buildNextBreadcrumbs(String id, String breadcrumbs) { | |
111 if (breadcrumbs == null) { | |
112 navigationBreadcrumbs = new String[] { id }; | |
113 return id; | |
114 } else { | |
115 String[] breadcrumbParts = breadcrumbs.split("-"); | |
116 navigationBreadcrumbs = new String[breadcrumbParts.length+1]; | |
117 int i = 0; | |
118 for (String s : breadcrumbParts) { | |
119 navigationBreadcrumbs[i++] = s; | |
120 } | |
121 navigationBreadcrumbs[i] = meaning.getId(); | |
122 return breadcrumbs + '-' + navigationBreadcrumbs[i]; | |
123 } | |
124 } | |
125 | |
126 @Command public void id(IPrintWriter out,Interpreter interp) { | |
127 out.print(meaning.getId()); | |
128 } | |
129 | |
130 @Command public void name(IPrintWriter out,Interpreter interp) { | |
131 out.print(meaning.getName()); | |
132 } | |
133 | |
134 @Command public void macro_overridden_id(IPrintWriter out,Interpreter interp) { | |
135 out.print(macroOverriddenId); | |
136 } | |
137 | |
138 @Command public void macro_which_overrides_id(IPrintWriter out,Interpreter interp) { | |
139 out.print(macroWhichOverridesId); | |
140 } | |
141 | |
142 @Command public void is_compiled(IPrintWriter out,Interpreter interp) { | |
143 out.print(meaning instanceof Macro && site.getProgram().isCompiled(meaning)); | |
144 } | |
145 | |
146 public static final CommandSpec documentation = requiresServletNamespace; | |
147 | |
148 @Command public void documentation(IPrintWriter out,Interpreter interp) | |
149 throws ServletException | |
150 { | |
151 String name = meaning.getName(); | |
152 Collection<String> namespaces = meaning.getRequiredNamespaces(); | |
153 Site site = NabbleNamespace.current().site(); | |
154 Template template = site.getTemplate(DocNamespace.getDocName(name,namespaces), BasicNamespace.class, NabbleNamespace.class, DocNamespace.class); | |
155 if( template == null && !namespaces.isEmpty() ) | |
156 template = site.getTemplate(DocNamespace.getDocName(name,Collections.<String>emptySet()), BasicNamespace.class, NabbleNamespace.class, DocNamespace.class); | |
157 if( template == null ) { | |
158 if( meaning instanceof JavaCommand ) { | |
159 JavaCommand jc = (JavaCommand)meaning; | |
160 CommandDoc doc = jc.getMethod().getAnnotation(CommandDoc.class); | |
161 | |
162 String value = doc == null? "" : doc.value(); | |
163 String[] params = doc == null? new String[0] : doc.params(); | |
164 String[] seeAlso = doc == null? new String[0] : doc.seeAlso(); | |
165 | |
166 template = site.getTemplate("binary doc", BasicNamespace.class, NabbleNamespace.class, DocNamespace.BinaryDocNamespace.class); | |
167 if( template != null ) { | |
168 DocNamespace.BinaryDocNamespace ns = new DocNamespace.BinaryDocNamespace(site, jc, value, params, seeAlso); | |
169 template.run(out,Collections.<String,Object>emptyMap(),new BasicNamespace(template), new NabbleNamespace(site), ns); | |
170 return; | |
171 } | |
172 } | |
173 template = site.getTemplate("doc not found",BasicNamespace.class,NabbleNamespace.class,DocNamespace.class); | |
174 } | |
175 DocNamespace ns = new DocNamespace(); | |
176 template.run(out,Collections.<String,Object>emptyMap(), new BasicNamespace(template), new NabbleNamespace(site), ns); | |
177 } | |
178 | |
179 public static final CommandSpec navigation_breadcrumbs = CommandSpec.DO; | |
180 | |
181 @Command public void navigation_breadcrumbs(IPrintWriter out, ScopedInterpreter<Parts> interp) { | |
182 List<CommandInfo> infos = new ArrayList<CommandInfo>(); | |
183 Program program = site.getProgram(); | |
184 StringBuilder breadCrumbs = new StringBuilder(); | |
185 for (String id : navigationBreadcrumbs) { | |
186 Meaning m = program.getMeaning(id); | |
187 // Skip broken meanings in the breadcrumbs | |
188 if (m != null) | |
189 infos.add(new CommandInfo(m,baseClasses,breadCrumbs.length() == 0? null : breadCrumbs.toString())); | |
190 if( breadCrumbs.length() > 0 ) | |
191 breadCrumbs.append('-'); | |
192 breadCrumbs.append(id); | |
193 } | |
194 out.print(interp.getArg(new Parts(infos),"do")); | |
195 } | |
196 | |
197 @Command public void source(IPrintWriter out, Interpreter interp) { | |
198 out.print(getSource(meaning)); | |
199 } | |
200 | |
201 @Command public void source_path(IPrintWriter out, Interpreter interp) { | |
202 String path = null; | |
203 if (meaning instanceof Macro) { | |
204 path = "/template/NamlEditor$ViewFile.jtp?file="+ ((Macro) meaning).source.toString(); | |
205 } | |
206 out.print(path); | |
207 } | |
208 | |
209 private static String getSource(Meaning m) { | |
210 if (m instanceof Macro) { | |
211 String source = ((Macro) m).source.toString(); | |
212 return source.endsWith(".naml")? source : source + ".naml"; | |
213 } | |
214 return null; | |
215 } | |
216 | |
217 @Command public void has_macro_overridden(IPrintWriter out,Interpreter interp) { | |
218 out.print(macroOverriddenId != null); | |
219 } | |
220 | |
221 @Command public void has_macro_which_overrides(IPrintWriter out,Interpreter interp) { | |
222 out.print(macroWhichOverridesId != null); | |
223 } | |
224 | |
225 @Command public void is_override(IPrintWriter out,Interpreter interp) { | |
226 out.print(isOverride(meaning)); | |
227 } | |
228 | |
229 private static boolean isOverride(Meaning meaning) { | |
230 if( !(meaning instanceof Macro) ) | |
231 return false; | |
232 return ((Macro) meaning).isOverride(); | |
233 } | |
234 | |
235 @Command public void is_custom_tweak(IPrintWriter out,Interpreter interp) { | |
236 out.print(isCustomTweak(meaning)); | |
237 } | |
238 | |
239 @Command public void is_configuration_tweak(IPrintWriter out,Interpreter interp) { | |
240 out.print(isConfigurationTweak(meaning)); | |
241 } | |
242 | |
243 private static boolean isCustomTweak(Meaning meaning) { | |
244 if( !(meaning instanceof Macro) ) | |
245 return false; | |
246 Source source = ((Macro) meaning).source; | |
247 return ModuleManager.isCustomTweak(source); | |
248 } | |
249 | |
250 private static boolean isConfigurationTweak(Meaning meaning) { | |
251 if( !(meaning instanceof Macro) ) | |
252 return false; | |
253 Source source = ((Macro) meaning).source; | |
254 return ModuleManager.isConfigurationTweak(source); | |
255 } | |
256 | |
257 @Command public void is_binary(IPrintWriter out,Interpreter interp) { | |
258 out.print(!(meaning instanceof Macro)); | |
259 } | |
260 | |
261 @Command public void tweak_file_contents(IPrintWriter out,Interpreter interp) { | |
262 String file = null; | |
263 if (meaning instanceof Macro) { | |
264 Macro macro = (Macro) meaning; | |
265 if (isCustomTweak(meaning)) { | |
266 file = macro.source.content; | |
267 } else { | |
268 file = macro.element.toString(); | |
269 file = file.replace("<macro ", "<override_macro "); | |
270 file = file.replace("</macro", "</override_macro"); | |
271 file = file.replace("<subroutine ", "<override_subroutine "); | |
272 file = file.replace("</subroutine", "</override_subroutine"); | |
273 file = file.replace("<translation ", "<override_translation "); | |
274 file = file.replace("</translation", "</override_translation"); | |
275 } | |
276 } | |
277 out.print(file); | |
278 } | |
279 | |
280 @Command public void macro_opening_tag(IPrintWriter out,Interpreter interp) { | |
281 String tag = null; | |
282 if (meaning instanceof Macro) { | |
283 Macro macro = (Macro) meaning; | |
284 tag = macro.element.openingTag(); | |
285 if (!isCustomTweak(meaning)) { | |
286 tag = tag.replace("<macro ", "<override_macro "); | |
287 tag = tag.replace("<subroutine ", "<override_subroutine "); | |
288 tag = tag.replace("<translation ", "<override_translation "); | |
289 } | |
290 } | |
291 out.print(tag); | |
292 } | |
293 | |
294 public static final CommandSpec rows = CommandSpec.DO; | |
295 | |
296 @Command public void rows(IPrintWriter out,ScopedInterpreter<Rows> interp) | |
297 throws IOException, ServletException | |
298 { | |
299 if (meaning instanceof Macro) { | |
300 Macro m = (Macro) meaning; | |
301 List<CommandInfo> infos = new ArrayList<CommandInfo>(); | |
302 List<Parts> rows = new ArrayList<Parts>(); | |
303 buildElement(m.element, infos, rows, false); | |
304 if (infos.size() > 0) | |
305 rows.add(new Parts(infos)); | |
306 | |
307 Object block = interp.getArg(new Rows(rows, m),"do"); | |
308 out.print(block); | |
309 } | |
310 } | |
311 | |
312 private void traverse(Naml naml, List<CommandInfo> parts, List<Parts> rows, boolean isAttribute) { | |
313 for (Object o : naml) { | |
314 if (o instanceof EmptyElement) { | |
315 buildEmptyElement((EmptyElement) o, parts, rows, isAttribute); | |
316 } else if (o instanceof Container) { | |
317 buildElement((Container) o, parts, rows, isAttribute); | |
318 } else { | |
319 processString(o.toString(), parts, rows); | |
320 } | |
321 } | |
322 } | |
323 | |
324 private void buildEmptyElement(EmptyElement e, List<CommandInfo> parts, List<Parts> rows, boolean isAttribute) { | |
325 startTag(parts, isAttribute); | |
326 extractParts(e, parts); | |
327 extractAttributes(e, parts, rows); | |
328 finishTag(e, parts, rows, isAttribute); | |
329 } | |
330 | |
331 private void buildElement(Element e, List<CommandInfo> parts, List<Parts> rows, boolean isAttribute) { | |
332 startTag(parts, isAttribute); | |
333 extractParts(e, parts); | |
334 | |
335 if (e.name().endsWithDot()) | |
336 parts.add(new CommandInfo(".")); | |
337 | |
338 extractAttributes(e, parts, rows); | |
339 finishTag(e, parts, rows, isAttribute); | |
340 if (e instanceof Container) { | |
341 Container container = (Container) e; | |
342 traverse(container.contents(), parts, rows, isAttribute); | |
343 closingTag(container, isAttribute, parts); | |
344 } | |
345 } | |
346 | |
347 private void closingTag(Container e, boolean isAttribute, List<CommandInfo> parts) { | |
348 String closingTag = e | |
349 .closingTag() | |
350 .replace("<",isAttribute?"[":"<") | |
351 .replace(">",isAttribute?"]":">"); | |
352 parts.add(new CommandInfo(closingTag)); | |
353 } | |
354 | |
355 private void finishTag(Element e, List<CommandInfo> infos, List<Parts> rows, boolean isAttribute) { | |
356 processString(e.spaceAtEndOfOpeningTag(), infos, rows); | |
357 infos.add(new CommandInfo( | |
358 (e instanceof EmptyElement? '/': "") + | |
359 (isAttribute? "]":">") | |
360 )); | |
361 } | |
362 | |
363 private void startTag(List<CommandInfo> parts, boolean isAttribute) { | |
364 parts.add(new CommandInfo(isAttribute?"[":"<")); | |
365 } | |
366 | |
367 private void extractAttributes(Element e, List<CommandInfo> parts, List<Parts> rows) { | |
368 for (Attribute attribute : e.attributes()) { | |
369 processString(attribute.spaceBeforeName(), parts, rows); | |
370 parts.add(new CommandInfo( | |
371 attribute.name() + | |
372 attribute.spaceAfterName() + | |
373 '=' + | |
374 attribute.quote()) | |
375 ); | |
376 traverse(attribute.value(), parts, rows, true); | |
377 parts.add(new CommandInfo(String.valueOf(attribute.quote()))); | |
378 } | |
379 } | |
380 | |
381 private void extractParts(Element e, List<CommandInfo> parts) { | |
382 int i = 0; | |
383 List<Macro> currentMacroPath = getCurrentMacroPath(); | |
384 Usage currentUsage = site.getProgram().getUsage(baseClassArray, currentMacroPath); | |
385 for (ElementName.Part p : e.name().parts()) { | |
386 if (i++ > 0) | |
387 parts.add(new CommandInfo(".")); | |
388 Meaning meaning = site.getProgram().getMeaning(p, currentUsage); | |
389 if (meaning != null) { | |
390 boolean isArgument = meaning instanceof ParamMeaning; | |
391 boolean isOverridden = "overridden".equals(p.text()); | |
392 if (isArgument || isOverridden) { | |
393 parts.add(new CommandInfo(p.text())); | |
394 } else { | |
395 parts.add(new CommandInfo(meaning, baseClasses, nextBreadcrumbs)); | |
396 } | |
397 } else | |
398 parts.add(new CommandInfo(p.text())); | |
399 } | |
400 } | |
401 | |
402 private List<Macro> getCurrentMacroPath() { | |
403 List<Macro> macroPath = new ArrayList<Macro>(); | |
404 Program program = site.getProgram(); | |
405 for (String id : navigationBreadcrumbs) { | |
406 macroPath.add((Macro) program.getMeaning(id)); | |
407 } | |
408 return macroPath; | |
409 } | |
410 | |
411 private void processString(String e, List<CommandInfo> infos, List<Parts> rows) { | |
412 StringBuilder builder = new StringBuilder(); | |
413 int i = 0; | |
414 while (i < e.length()) { | |
415 char c = e.charAt(i); | |
416 if (c == ' ') | |
417 builder.append(" "); | |
418 else if (c == '\t') | |
419 builder.append(" "); | |
420 else if ((c == '\r' && e.charAt(i+1) == '\n') || c == '\n') { | |
421 if (builder.length() > 0) { | |
422 infos.add(new CommandInfo(builder.toString())); | |
423 builder.setLength(0); | |
424 } | |
425 rows.add(new Parts(new ArrayList<CommandInfo>(infos))); | |
426 infos.clear(); | |
427 if (c == '\r') | |
428 i++; // CRLF | |
429 } else if (c == '<') { | |
430 builder.append("<"); | |
431 } else if (c == '>') { | |
432 builder.append(">"); | |
433 } else if (c == '&') { | |
434 builder.append("&"); | |
435 } else | |
436 builder.append(c); | |
437 i++; | |
438 } | |
439 if (builder.length() > 0) | |
440 infos.add(new CommandInfo(builder.toString())); | |
441 } | |
442 | |
443 static String csv(Collection<String> strings) { | |
444 StringBuilder b = new StringBuilder(); | |
445 for (String s : strings) { | |
446 if (b.length() > 0) | |
447 b.append(", "); | |
448 b.append(s); | |
449 } | |
450 return b.toString(); | |
451 } | |
452 | |
453 @Namespace ( | |
454 name = "macro_row_list", | |
455 global = true | |
456 ) | |
457 public static final class Rows extends ListSequence<Parts> | |
458 { | |
459 | |
460 private final Macro macro; | |
461 | |
462 Rows(List<Parts> rows, Macro macro) { | |
463 super(rows); | |
464 this.macro = macro; | |
465 } | |
466 | |
467 @Command public void line_number(IPrintWriter out,Interpreter interp) { | |
468 out.print(index + 1); | |
469 } | |
470 | |
471 @Command public void file_line_number(IPrintWriter out,Interpreter interp) { | |
472 out.print(macro.element.lineNumber() + index + 1); | |
473 } | |
474 | |
475 public static final CommandSpec current_row = CommandSpec.DO; | |
476 | |
477 @Command public void current_row(IPrintWriter out,ScopedInterpreter<Parts> interp) { | |
478 out.print(interp.getArg(get(),"do")); | |
479 } | |
480 | |
481 @Command public void next_row(IPrintWriter out,Interpreter interp) { | |
482 next_element(out,interp); | |
483 } | |
484 } | |
485 | |
486 @Namespace ( | |
487 name = "macro_parts_list", | |
488 global = true | |
489 ) | |
490 public static final class Parts extends ListSequence<CommandInfo> { | |
491 | |
492 Parts(List<CommandInfo> infos) { | |
493 super(infos); | |
494 } | |
495 | |
496 public static final CommandSpec parts = CommandSpec.DO; | |
497 | |
498 @Command public void parts(IPrintWriter out,ScopedInterpreter<CommandInfo> interp) { | |
499 out.print( interp.getArg(get(),"do") ); | |
500 } | |
501 | |
502 @Command public void is_blank(IPrintWriter out, Interpreter interp) { | |
503 out.print(elements.size() == 0); | |
504 } | |
505 } | |
506 | |
507 public static final CommandSpec macro_usages = CommandSpec.DO; | |
508 | |
509 @Command public void macro_usages(IPrintWriter out,ScopedInterpreter<MacroUsages> interp) | |
510 throws IOException, ServletException, CompileException | |
511 { | |
512 List<Commands> macros = new ArrayList<Commands>(); | |
513 Set<Usage> usages = site.getProgram().getUsages(meaning); | |
514 if (usages == null) | |
515 usages = new HashSet<Usage>(); | |
516 for (Usage u : usages) { | |
517 List<CommandInfo> infos = new ArrayList<CommandInfo>(); | |
518 StringBuilder breadcrumbs = new StringBuilder(); | |
519 String usageBase = asBaseParam(u.baseIds()); | |
520 for (Macro m : u.macroPath()) { | |
521 infos.add(new CommandInfo(m, usageBase, breadcrumbs.length() == 0? null : breadcrumbs.toString())); | |
522 | |
523 if (breadcrumbs.length() > 0) | |
524 breadcrumbs.append('-'); | |
525 breadcrumbs.append(m.getId()); | |
526 } | |
527 infos.add(new CommandInfo(meaning, usageBase, breadcrumbs.toString())); | |
528 macros.add(new Commands(infos)); | |
529 } | |
530 Object block = interp.getArg(new MacroUsages(macros),"do"); | |
531 out.print(block); | |
532 } | |
533 | |
534 static String asBaseParam(String[] base) { | |
535 StringBuilder b = new StringBuilder(); | |
536 for (String c : base) { | |
537 if (b.length() > 0) | |
538 b.append('-'); | |
539 b.append(c); | |
540 } | |
541 return b.toString(); | |
542 } | |
543 | |
544 static String asBreadcrumbsParam(List<Macro> macroPath) { | |
545 StringBuilder breadcrumbs = new StringBuilder(); | |
546 for (Macro p : macroPath) { | |
547 if (breadcrumbs.length() > 0) | |
548 breadcrumbs.append('-'); | |
549 breadcrumbs.append(p.getId()); | |
550 } | |
551 return breadcrumbs.toString(); | |
552 } | |
553 | |
554 @Namespace ( | |
555 name = "macro_usages", | |
556 global = true | |
557 ) | |
558 public static final class MacroUsages extends ListSequence<Commands> | |
559 { | |
560 public MacroUsages(List<Commands> elements) { | |
561 super(elements); | |
562 } | |
563 | |
564 public static final CommandSpec current_usage = CommandSpec.DO; | |
565 | |
566 @Command public void current_usage(IPrintWriter out,ScopedInterpreter<Commands> interp) { | |
567 out.print(interp.getArg(get(),"do")); | |
568 } | |
569 } | |
570 | |
571 @Namespace ( | |
572 name = "command_list", | |
573 global = true | |
574 ) | |
575 public static final class Commands extends ListSequence<CommandInfo> | |
576 { | |
577 public Commands(List<CommandInfo> elements) { | |
578 super(elements); | |
579 } | |
580 | |
581 public static final CommandSpec current_command = CommandSpec.DO; | |
582 | |
583 @Command public void current_command(IPrintWriter out,ScopedInterpreter<CommandInfo> interp) { | |
584 out.print(interp.getArg(get(),"do")); | |
585 } | |
586 } | |
587 | |
588 @Namespace ( | |
589 name = "command_info", | |
590 global = false | |
591 ) | |
592 public static final class CommandInfo { | |
593 private final String id; | |
594 private final String name; | |
595 private final String tag; | |
596 private final String source; | |
597 private final int fileLineNumber; | |
598 private final String baseClasses; | |
599 private final String breadcrumbs; | |
600 private final String requiredNamespaces; | |
601 private final boolean isCustomTweak; | |
602 private final boolean isMacro; | |
603 private final boolean isBinary; | |
604 private final String namespaceClass; | |
605 private final String[] parameterNames; | |
606 | |
607 static final Comparator<? super CommandInfo> MACRO_NAME_COMPARATOR = new Comparator<MacroSourceNamespace.CommandInfo>() { | |
608 public int compare(MacroSourceNamespace.CommandInfo o1, MacroSourceNamespace.CommandInfo o2) { | |
609 return o1.name.compareTo(o2.name); | |
610 } | |
611 }; | |
612 | |
613 public CommandInfo(String name) { | |
614 this.id = null; | |
615 this.tag = name; | |
616 this.name = name; | |
617 this.isMacro = false; | |
618 this.isBinary = false; | |
619 this.source = null; | |
620 this.fileLineNumber = 0; | |
621 this.baseClasses = null; | |
622 this.breadcrumbs = null; | |
623 this.requiredNamespaces = null; | |
624 this.isCustomTweak = false; | |
625 this.namespaceClass = null; | |
626 this.parameterNames = null; | |
627 } | |
628 | |
629 public CommandInfo(Meaning meaning, String baseClasses, String breadcrumbs) { | |
630 this.id = meaning.getId(); | |
631 this.name = meaning.getName(); | |
632 this.tag = this.name.startsWith("translation:")? "t" : this.name; | |
633 this.isMacro = meaning instanceof Macro; | |
634 this.isBinary = meaning instanceof JavaCommand; | |
635 this.source = getSource(meaning); | |
636 this.fileLineNumber = isMacro? ((Macro) meaning).element.lineNumber() + 1 : 0; | |
637 this.baseClasses = baseClasses; | |
638 this.breadcrumbs = breadcrumbs; | |
639 this.requiredNamespaces = csv(meaning.getRequiredNamespaces()); | |
640 this.isCustomTweak = isCustomTweak(meaning); | |
641 this.namespaceClass = meaning instanceof JavaCommand? ((JavaCommand) meaning).getMethod().getDeclaringClass().getSimpleName() : null; | |
642 this.parameterNames = isMacro? ((Macro) meaning).getParameterNames() : meaning instanceof JavaCommand? ((JavaCommand) meaning).getParameterNames() : null; | |
643 } | |
644 | |
645 @Command("id") public void _id(IPrintWriter out,Interpreter interp) { | |
646 out.print(id); | |
647 } | |
648 | |
649 @Command("name") public void _name(IPrintWriter out,Interpreter interp) { | |
650 out.print(name); | |
651 } | |
652 | |
653 @Command("tag") public void _tag(IPrintWriter out,Interpreter interp) { | |
654 out.print(tag); | |
655 } | |
656 | |
657 @Command("source") public void _source(IPrintWriter out,Interpreter interp) { | |
658 out.print(source); | |
659 } | |
660 | |
661 @Command public void naml_breadcrumbs(IPrintWriter out,Interpreter interp) { | |
662 out.print(breadcrumbs); | |
663 } | |
664 | |
665 @Command public void base(IPrintWriter out,Interpreter interp) { | |
666 out.print(baseClasses); | |
667 } | |
668 | |
669 @Command public void file_line_number(IPrintWriter out,Interpreter interp) { | |
670 out.print(fileLineNumber); | |
671 } | |
672 | |
673 @Command public void required_namespaces(IPrintWriter out,Interpreter interp) { | |
674 out.print(requiredNamespaces); | |
675 } | |
676 | |
677 @Command public void is_custom_tweak(IPrintWriter out,Interpreter interp) { | |
678 out.print(isCustomTweak); | |
679 } | |
680 | |
681 @Command public void is_macro(IPrintWriter out,Interpreter interp) { | |
682 out.print(isMacro); | |
683 } | |
684 | |
685 @Command public void namespace_class(IPrintWriter out,Interpreter interp) { | |
686 out.print(namespaceClass); | |
687 } | |
688 | |
689 @Command public void is_binary(IPrintWriter out,Interpreter interp) { | |
690 out.print(isBinary); | |
691 } | |
692 | |
693 @Command public void has_parameters(IPrintWriter out,Interpreter interp) { | |
694 out.print(parameterNames != null && parameterNames.length > 0); | |
695 } | |
696 | |
697 public static final CommandSpec parameter_names = CommandSpec.DO; | |
698 | |
699 @Command public void parameter_names(IPrintWriter out, ScopedInterpreter<StringList> interp) { | |
700 out.print(interp.getArg(new StringList(Arrays.asList(parameterNames)),"do")); | |
701 } | |
702 } | |
703 } |