0
|
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 }
|