Mercurial Hosting > nabble
diff src/nabble/naml/namespaces/BasicNamespace.java @ 0:7ecd1a4ef557
add content
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Thu, 21 Mar 2019 19:15:52 -0600 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/nabble/naml/namespaces/BasicNamespace.java Thu Mar 21 19:15:52 2019 -0600 @@ -0,0 +1,1064 @@ +package nabble.naml.namespaces; + +import fschmidt.util.java.ArrayStack; +import fschmidt.util.java.ObjectUtils; +import fschmidt.util.java.Stack; +import fschmidt.util.mail.MailAddress; +import nabble.naml.compiler.Command; +import nabble.naml.compiler.CommandSpec; +import nabble.naml.compiler.CompileException; +import nabble.naml.compiler.Encoder; +import nabble.naml.compiler.ExitException; +import nabble.naml.compiler.IPrintWriter; +import nabble.naml.compiler.Interpreter; +import nabble.naml.compiler.JavaCommand; +import nabble.naml.compiler.Macro; +import nabble.naml.compiler.Namespace; +import nabble.naml.compiler.ScopedInterpreter; +import nabble.naml.compiler.StackTrace; +import nabble.naml.compiler.Template; +import nabble.naml.compiler.TemplateRuntimeException; +import nabble.naml.compiler.NamlNullPointerException; +import nabble.view.web.template.DateNamespace; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Random; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + + +@Namespace ( + name = "basic", + global = true +) +public final class BasicNamespace { + private static final Logger logger = LoggerFactory.getLogger(BasicNamespace.class); + + private final Template template; + + public BasicNamespace(Template template) { + this.template = template; + } + + public static final CommandSpec exit = CommandSpec.NO_OUTPUT; + + @CommandDoc( + "Exits the page generation and returns the control back to the browser." + ) + @Command public void exit(IPrintWriter out,Interpreter interp) { + throw new ExitException(); + } + + public static final CommandSpec throw_runtime_exception = new CommandSpec.Builder() + .dotParameter("text") + .outputtedParameters() + .build() + ; + + @CommandDoc( + value= "Throws a runtime exception to show that something is wrong or broken. "+ + "If this command is called, the page will display the full stack trace of the error, which "+ + "should be investigated and fixed.", + params = {"text=The message displayed by the exception"}, + seeAlso = {"throw_template_exception"} + ) + @Command public void throw_runtime_exception(IPrintWriter out,Interpreter interp) { + String text = interp.getArgString("text"); + throw new RuntimeException(text); + } + + public static final CommandSpec throw_template_exception = new CommandSpec.Builder() + .dotParameter("name") + .build() + ; + + @CommandDoc( + value= "Throws an exception that can be caught by the @link{catch_exception} command.", + params = {"name=The name of the exception, which should be used later for catching and handling."}, + seeAlso = {"ExceptionNamespace.exception"} + ) + @Command public void throw_template_exception(IPrintWriter out,Interpreter interp) + throws TemplateException + { + String name = interp.getArgString("name"); + throw TemplateException.newInstance(name); + } + + @Command("true") public static void _true(IPrintWriter out,Interpreter interp) { + out.print(true); + } + + @Command("false") public static void _false(IPrintWriter out,Interpreter interp) { + out.print(false); + } + + public static final CommandSpec either = new CommandSpec.Builder() + .parameters("condition1","condition2") + .build() + ; + + @Command public static void either(IPrintWriter out,Interpreter interp) { + out.print( interp.getArgAsBoolean("condition1") || interp.getArgAsBoolean("condition2") ); + } + + public static final CommandSpec both = new CommandSpec.Builder() + .parameters("condition1","condition2") + .build() + ; + + @Command public static void both(IPrintWriter out,Interpreter interp) { + out.print( interp.getArgAsBoolean("condition1") && interp.getArgAsBoolean("condition2") ); + } + + public static final CommandSpec _if = new CommandSpec.Builder() + .dotParameter("condition") + .optionalParameters("then","else") + .outputtedParameters("then","else") + .dontRemoveNulls() + .build() + ; + + @CommandDoc( + value= "Calls the \"then\" block if the 'condition' (dot_parameter) is true. " + + "Otherwise, calls the \"else\" block (if available).", + params = { + "condition=Condition to be tested", + "then=Block for the true case", + "else=Block for the false case" + } + ) + @Command("if") public static void _if(IPrintWriter out,Interpreter interp) { + Object block = interp.getArg( interp.getArgAsBoolean("condition") ? "then" : "else" ); + if( block != null ) + out.print(block); + } + + public static final CommandSpec not = new CommandSpec.Builder() + .dotParameter("condition") + .build() + ; + + @Command public static void not(IPrintWriter out,Interpreter interp) { + out.print( !interp.getArgAsBoolean("condition") ); + } + + private static final CommandSpec optionalValue = new CommandSpec.Builder() + .dotParameter("value") + .optionalParameters("value") + .build() + ; + + public static final CommandSpec hide_null = optionalValue; + + @Command public static void hide_null(IPrintWriter out,Interpreter interp) { + String s = interp.getArgString("value"); + if( s != null ) + out.print(s); + } + + + public static final CommandSpec is_null = optionalValue; + + @Command public static void is_null(IPrintWriter out,Interpreter interp) { + String s = interp.getArgString("value"); + out.print( s==null ); + } + + @Command("null") public static void _null(IPrintWriter out,Interpreter interp) { + out.print((String)null); + } + + public static final CommandSpec null_exception_to_null = optionalValue; + + @Command public static void null_exception_to_null(IPrintWriter out,Interpreter interp) { + try { + out.print( interp.getArgString("value") ); + } catch(NamlNullPointerException e) { + out.print( (String)null ); + } + } + + private static final Random RANDOM = new Random(); + + public static final CommandSpec random = new CommandSpec.Builder() + .parameters("max") + .build() + ; + + @Command public void random(IPrintWriter out,Interpreter interp) { + int max = interp.getArgAsInt("max"); + int r = RANDOM.nextInt(max); + out.print(r); + } + + public static final CommandSpec equal = new CommandSpec.Builder() + .optionalParameters("value1","value2") + .build() + ; + + @Command public static void equal(IPrintWriter out,Interpreter interp) { + out.print( ObjectUtils.equals(interp.getArgString("value1"),interp.getArgString("value2")) ); + } + + public static final CommandSpec starts_with = new CommandSpec.Builder() + .dotParameter("text") + .parameters("prefix") + .build() + ; + + @Command public void starts_with(IPrintWriter out,Interpreter interp) { + String text = interp.getArgString("text"); + String prefix = interp.getArgString("prefix"); + out.print( text.startsWith(prefix) ); + } + + public static final CommandSpec ends_with = new CommandSpec.Builder() + .dotParameter("text") + .parameters("suffix") + .build() + ; + + @Command public void ends_with(IPrintWriter out,Interpreter interp) { + String text = interp.getArgString("text"); + String suffix = interp.getArgString("suffix"); + out.print( text.endsWith(suffix) ); + } + + public static final CommandSpec substring = new CommandSpec.Builder() + .dotParameter("text") + .parameters("begin") + .optionalParameters("end") + .build() + ; + + @Command public void substring(IPrintWriter out,Interpreter interp) { + String text = interp.getArgString("text"); + int begin = Integer.parseInt(interp.getArgString("begin")); + String end = interp.getArgString("end"); + out.print( end==null ? text.substring(begin) : text.substring(begin,Integer.parseInt(end)) ); + } + + public static final CommandSpec contains_substring = new CommandSpec.Builder() + .dotParameter("string") + .parameters("substring") + .build() + ; + + @Command public void contains_substring(IPrintWriter out,Interpreter interp) { + out.print( interp.getArgString("string").indexOf(interp.getArgString("substring")) != -1 ); + } + + public static final CommandSpec regex_quote = new CommandSpec.Builder() + .dotParameter("string") + .build() + ; + + @Command public void regex_quote(IPrintWriter out,Interpreter interp) { + out.print( Pattern.quote(interp.getArgString("string")) ); + } + + public static final CommandSpec append = new CommandSpec.Builder() + .dotParameter("text") + .parameters("suffix") + .optionalParameters("text","except_if") + .restrictedParameter("except_if","already-included") + .build() + ; + + @Command public void append(IPrintWriter out,Interpreter interp) { + String text = interp.getArgString("text"); + out.print(text); + if( text!=null && text.length() > 0 ) { + String suffix = interp.getArgString("suffix"); + if( !( "already-included".equals(interp.getArgString("except_if")) + && text.toLowerCase().indexOf(suffix.toLowerCase()) != -1 + ) ) + out.print(suffix); + } + } + + public static final CommandSpec prepend = new CommandSpec.Builder() + .dotParameter("text") + .parameters("prefix") + .optionalParameters("text","except_if") + .restrictedParameter("except_if","already-included") + .build() + ; + + @Command public void prepend(IPrintWriter out,Interpreter interp) { + String text = interp.getArgString("text"); + if( text!=null && text.length() > 0 ) { + String prefix = interp.getArgString("prefix"); + if( !( "already-included".equals(interp.getArgString("except_if")) + && text.toLowerCase().indexOf(prefix.toLowerCase()) != -1 + ) ) + out.print(prefix); + } + out.print(text); + } + + public static final CommandSpec separate = new CommandSpec.Builder() + .parameters("text1","separator","text2") + .build() + ; + + @Command public void separate(IPrintWriter out,Interpreter interp) { + String text1 = interp.getArgString("text1"); + if( text1 == null ) + throw new NullPointerException("text1 is null"); + String text2 = interp.getArgString("text2"); + if( text2 == null ) + throw new NullPointerException("text2 is null"); + out.print( text1 ); + if( text1.trim().length() > 0 && text2.trim().length() > 0 ) + out.print( interp.getArg("separator") ); + out.print( text2 ); + } + +/* + public static final CommandSpec is_in_namespace = new CommandSpec.Builder() + .parameters("name") + .build() + ; + + @Command public static void is_in_namespace(IPrintWriter out,Interpreter interp) { + out.print( interp.hasNamespace(interp.getArgString("name")) ); + } +*/ + + public static final CommandSpec is_in_command = new CommandSpec.Builder() + .parameters("name") + .build() + ; + + @Command public static void is_in_command(IPrintWriter out,Interpreter interp) { + out.print( interp.isInCommandStack(interp.getArgString("name")) ); + } + + + public static final CommandSpec to_lower_case = CommandSpec.TEXT; + + @Command public void to_lower_case(IPrintWriter out,Interpreter interp) { + out.print( interp.getArgString("text").toLowerCase() ); + } + + public static final CommandSpec to_upper_case = CommandSpec.TEXT; + + @Command public void to_upper_case(IPrintWriter out,Interpreter interp) { + out.print( interp.getArgString("text").toUpperCase() ); + } + + public static final CommandSpec capitalize = CommandSpec.TEXT; + + @Command public void capitalize(IPrintWriter out,Interpreter interp) { + String text = interp.getArgString("text"); + String[] words = text.split("[ ]"); + StringBuilder b = new StringBuilder(); + for (String w : words) { + if (b.length() > 0) + b.append(' '); + b.append(w.substring(0,1).toUpperCase()); + b.append(w.substring(1,w.length())); + } + out.print(b.toString()); + } + + public static final CommandSpec regex = new CommandSpec.Builder() + .parameters("pattern","text") + .scopedParameters("do") + .dotParameter("do") + .build() + ; + + @Command public static void regex(IPrintWriter out,ScopedInterpreter<RegexNamespace> interp) { + Pattern p = Pattern.compile( interp.getArgString("pattern") ); + String s = interp.getArgString("text"); + Matcher m = p.matcher(s); + RegexNamespace ns = new RegexNamespace(m,s); + out.print( interp.getArg(ns,"do") ); + } + + public static final CommandSpec regex_replace_all = new CommandSpec.Builder() + .dotParameter("text") + .parameters("pattern","replacement") + .build() + ; + + @Command public static void regex_replace_all(IPrintWriter out,Interpreter interp) { + String text = interp.getArgString("text"); + String pattern = interp.getArgString("pattern"); + String replacement = interp.getArgString("replacement"); + out.print( text.replaceAll(pattern, replacement) ); + } + + public static final CommandSpec regex_replace_first = new CommandSpec.Builder() + .dotParameter("text") + .parameters("pattern","replacement") + .build() + ; + + @Command public static void regex_replace_first(IPrintWriter out,Interpreter interp) { + String text = interp.getArgString("text"); + String pattern = interp.getArgString("pattern"); + String replacement = interp.getArgString("replacement"); + out.print( text.replaceFirst(pattern, replacement) ); + } + + public static final CommandSpec string_replace_all = new CommandSpec.Builder() + .dotParameter("text") + .parameters("target","replacement") + .build() + ; + + @Command public static void string_replace_all(IPrintWriter out,Interpreter interp) { + out.print( interp.getArgString("text").replace(interp.getArgString("target"),interp.getArgString("replacement")) ); + } + + public static final CommandSpec trim = CommandSpec.TEXT; + + @Command public static void trim(IPrintWriter out,Interpreter interp) { + String s = interp.getArgString("text"); + out.print( s==null ? null : s.trim() ); + } + + public static final CommandSpec encode = CommandSpec.OPTIONAL_TEXT; + + @Command public static void encode(IPrintWriter out,Interpreter interp) { + String s = interp.getArgString("text"); + out.print( interp.encode(s) ); + } + + public static final CommandSpec use_text_encoder = CommandSpec.OPTIONAL_TEXT; + + @Command public void use_text_encoder(IPrintWriter out,Interpreter interp) { + interp.setEncoder(Encoder.TEXT); + String s = interp.getArgString("text"); + out.print(s); + } + + public static final CommandSpec use_html_encoder = CommandSpec.OPTIONAL_TEXT; + + @Command public void use_html_encoder(IPrintWriter out,Interpreter interp) { + interp.setEncoder(Encoder.HTML); + String s = interp.getArgString("text"); + out.print(s); + } + + public static final CommandSpec use_url_encoder = CommandSpec.OPTIONAL_TEXT; + + @Command public void use_url_encoder(IPrintWriter out,Interpreter interp) { + interp.setEncoder(Encoder.URL); + String s = interp.getArgString("text"); + out.print(s); + } + + public static final CommandSpec is_empty = optionalValue; + + @Command public static void is_empty(IPrintWriter out,Interpreter interp) { + String s = interp.getArgString("value"); + out.print( s==null || s.length() == 0 ); + } + + + public static final CommandSpec var = new CommandSpec.Builder() + .parameters("name") + .build() + ; + + @Command public void var(IPrintWriter out,Interpreter interp) { + throw new RuntimeException("never"); + } + + public static final CommandSpec set_var = new CommandSpec.Builder() + .parameters("name") + .dotParameter("value") + .optionalParameters("value") + .outputtedParameters() + .build() + ; + + @Command public void set_var(IPrintWriter out,Interpreter interp) { + throw new RuntimeException("never"); + } + + public static final CommandSpec uplevel_var = var; + + @Command public void uplevel_var(IPrintWriter out,Interpreter interp) { + throw new RuntimeException("never"); + } + + public static final CommandSpec uplevel_set_var = set_var; + + @Command public void uplevel_set_var(IPrintWriter out,Interpreter interp) { + throw new RuntimeException("never"); + } + + private final Map<String,String> globalVars = new HashMap<String,String>(); + + public static final CommandSpec global_var = var; + + @Command public void global_var(IPrintWriter out,Interpreter interp) { + String name = interp.getArgString("name"); + out.print( globalVars.get(name) ); + } + + public static final CommandSpec global_set_var = set_var; + + @Command public void global_set_var(IPrintWriter out,Interpreter interp) { + String name = interp.getArgString("name"); + String value = interp.getArgString("value"); + globalVars.put(name,value); + } + + public static final CommandSpec global_is_var_set = var; + + @Command public void global_is_var_set(IPrintWriter out,Interpreter interp) { + String name = interp.getArgString("name"); + out.print( globalVars.containsKey(name) ); + } + + + public static final CommandSpec _default = new CommandSpec.Builder() + .dotParameter("text") + .optionalParameters("text") + .parameters("to") + .build() + ; + + @Command("default") public static void _default(IPrintWriter out,Interpreter interp) { + String text = interp.getArgString("text"); + out.print( text!=null ? text : interp.getArgString("to") ); + } + + private static final int whileLimit = 1000000; + + private static class BreakException extends TemplateRuntimeException { + BreakException() { + super("break called outside of while"); + } + } + + public static final CommandSpec _while = new CommandSpec.Builder() + .dotParameter("condition") + .parameters("loop") + .outputtedParameters("loop") + .build() + ; + + @Command("while") public void _while(IPrintWriter out,Interpreter interp) { + Object condition = interp.getArg("condition"); + Object block = interp.getArg("loop"); + int count = 0; + try { + while( Template.booleanValue(condition) ) { + if( ++count > whileLimit ) + throw new RuntimeException("while loop limit of "+whileLimit+" iterations exceeded"); + out.print(block); + } + } catch(BreakException e) {} + } + + @Command("break") public void _break(IPrintWriter out,Interpreter interp) { + throw new BreakException(); + } + + + @Command public void nop(IPrintWriter out,Interpreter interp) {} + + + private static final class ExceptionInfo { + private final String forStr; + private final TemplateException ex; + + private ExceptionInfo(String forStr,TemplateException ex) { + this.forStr = forStr; + this.ex = ex; + } + } + + private Stack<ExceptionInfo> exceptionStack = new ArrayStack<ExceptionInfo>(); + + public static final CommandSpec catch_exception = new CommandSpec.Builder() + .parameters("id") + .dotParameter("do") + .outputtedParameters("do") + .build() + ; + + @Command public void catch_exception(IPrintWriter out,Interpreter interp) { + String idStr = interp.getArgString("id"); + TemplateException ex = null; + try { + out.print( interp.getArg("do") ); + } catch(TemplateRuntimeException e) { + Throwable cause = e.getCause(); + if( cause instanceof TemplateException ) { + ex = (TemplateException)cause; + } else { + throw e; + } + } + exceptionStack.push( new ExceptionInfo(idStr,ex) ); + } + + @Namespace ( + name = "error", + global = false + ) + public static class ExceptionNamespace { + protected final TemplateException ex; + protected boolean isDone = false; + + public ExceptionNamespace(TemplateException ex) { + this.ex = ex; + } + + public static final CommandSpec exception = new CommandSpec.Builder() + .parameters("name") + .dotParameter("do") + .build() + ; + + @Command public void exception(IPrintWriter out,Interpreter interp) { + if( isDone ) + return; + String name = interp.getArgString("name"); + if( ex.isNamed(name) ) { + out.print( interp.getArg("do") ); + isDone = true; + } + } + + public static final CommandSpec unknown_exception = CommandSpec.DO; + + @Command public void unknown_exception(IPrintWriter out,ScopedInterpreter<UnknownException> interp) { + if( isDone ) + return; + out.print( interp.getArg(new UnknownException(ex), "do") ); + isDone = true; + } + + protected static final CommandSpec scopedCommandSpec = new CommandSpec.Builder() + .parameters("name") + .dotParameter("do") + .scopedParameters("do") + .build() + ; + + protected final <N> void scopedException(IPrintWriter out,ScopedInterpreter<N> interp,N ns) { + if( isDone ) + return; + String name = interp.getArgString("name"); + if( ex.isNamed(name) ) { + out.print(interp.getArg(ns,"do")); + isDone = true; + } + } + + protected final <N> void unnamedScopedException(IPrintWriter out,ScopedInterpreter<N> interp,N ns) { + if( isDone ) + return; + out.print(interp.getArg(ns,"do")); + isDone = true; + } + + } + + @Namespace ( + name = "unknown_exception", + global = false + ) + public static class UnknownException extends ExceptionNamespace { + + public UnknownException(TemplateException ex) { + super(ex); + } + + @Command public void message(IPrintWriter out,Interpreter interp) { + out.print(ex.getMessage()); + } + } + + public static interface ExceptionNamespaceFactory<E extends ExceptionNamespace> { + public E newExceptionNamespace(TemplateException ex); + } + +/* private static final ExceptionNamespaceFactory<ExceptionNamespace> myExceptionNamespaceFactory = + new ExceptionNamespaceFactory<ExceptionNamespace>() { + public ExceptionNamespace newExceptionNamespace(TemplateException ex) { + return new ExceptionNamespace(ex); + } + } + ;*/ + + public static final CommandSpec handle_exception = CommandSpec.DO() + .parameters("for") + .requiredInStack(BasicNamespace.class) + .build() + ; +/* + @Command public void handle_exception(IPrintWriter out,ScopedInterpreter<ExceptionNamespace> interp) { + handleException(out,interp,myExceptionNamespaceFactory); + } +*/ + public <E extends ExceptionNamespace> void handleException(IPrintWriter out,ScopedInterpreter<E> interp,ExceptionNamespaceFactory<E> factory) { + if( exceptionStack.isEmpty() ) + throw new RuntimeException("there are no exceptions available to be handled"); + ExceptionInfo ei = exceptionStack.pop(); + String forStr = interp.getArgString("for"); + if( !forStr.equals(ei.forStr) ) + throw new RuntimeException("found exception for: "+ei.forStr); + if( ei.ex == null ) + return; + E en = factory.newExceptionNamespace(ei.ex); + out.print( interp.getArg(en,"do") ); + if( !en.isDone ) { + logger.error("unexpected exception"+StackTrace.current(),en.ex); + out.print( "Unexpected exception: " + en.ex ); + } + } + + public static final CommandSpec has_exception = new CommandSpec.Builder() + .parameters("for") + .build() + ; + + @Command public void has_exception(IPrintWriter out,Interpreter interp) { + if( exceptionStack.isEmpty() ) + throw new RuntimeException("there are no exceptions available to be handled"); + ExceptionInfo ei = exceptionStack.peek(); + String forStr = interp.getArgString("for"); + if( !forStr.equals(ei.forStr) ) + throw new RuntimeException("found exception for: "+ei.forStr); + out.print( ei.ex != null ); + } + + public static final CommandSpec string_list = CommandSpec.DO() + .optionalParameters("values","separator","trim") + .build() + ; + + @Command public void string_list(IPrintWriter out,ScopedInterpreter<StringList> interp) { + List<String> list = new ArrayList<String>(); + String csv = interp.getArgString("values"); + if( csv != null ) { + String separator = interp.getArgString("separator"); + if( separator == null ) + separator = ","; + boolean trim = interp.getArgAsBoolean("trim", true); + for( String s : csv.split(separator) ) { + list.add( trim? s.trim() : s ); + } + } + Object block = interp.getArg(new StringList(list),"do"); + out.print(block); + } + + public static final CommandSpec string_map = new CommandSpec.Builder() + .parameters("key") + .dotParameter("entries") + .build() + ; + + @Command public void string_map(IPrintWriter out, Interpreter interp) { + String key = interp.getArgString("key"); + String[] entries = interp.getArgString("entries").split("\n"); + for (String entry : entries) { + String[] keyValue = entry.split(":"); + if (key.equals(keyValue[0].trim())) { + out.print(keyValue[1].trim()); + return; + } + } + out.print((String) null); + } + + public static final CommandSpec _int = CommandSpec.DO() + .parameters("i") + .build() + ; + + @Command("int") public void _int(IPrintWriter out,ScopedInterpreter<IntegerNamespace> interp) { + out.print( interp.getArg(new IntegerNamespace(interp.getArgAsInt("i")),"do") ); + } + + public static final CommandSpec extract_email_address_from = new CommandSpec.Builder() + .dotParameter("text") + .build() + ; + + @Command public static void extract_email_address_from(IPrintWriter out,Interpreter interp) { + String text = interp.getArgString("text").trim(); + String email = null; + if (new MailAddress(text).isValid()) { + email = text; + } else { + int posOpen = text.lastIndexOf('<'); + int posClose = text.lastIndexOf('>'); + if (posOpen >= 0 && posClose > posOpen) { + String middle = text.substring(posOpen+1, posClose); + if (new MailAddress(middle).isValid()) + email = middle; + } + } + out.print(email); + } + + @Command public void crlf(IPrintWriter out,Interpreter interp) { + out.print("\r\n"); + } + + @Command public void space(IPrintWriter out,Interpreter interp) { + out.print(' '); + } + + @Command public void double_quote(IPrintWriter out,Interpreter interp) { + out.print("\""); + } + + public static final CommandSpec has_module = new CommandSpec.Builder() + .dotParameter("module") + .build() + ; + + @Command public static void has_module(IPrintWriter out,Interpreter interp) { + out.print( interp.hasModule(interp.getArgString("module")) ); + } + + public static final CommandSpec no_output = CommandSpec.NO_OUTPUT() + .dotParameter("text") + .build() + ; + + @Command public static void no_output(IPrintWriter out,Interpreter interp) { + interp.getArgString("text"); + } + + + @Command public static void lt(IPrintWriter out,Interpreter interp) { + out.print('<'); + } + + @Command public static void gt(IPrintWriter out,Interpreter interp) { + out.print('>'); + } + + public static final CommandSpec now = CommandSpec.DO; + + @Command public void now(IPrintWriter out,ScopedInterpreter<DateNamespace> interp) { + out.print( interp.getArg(new DateNamespace(new Date()), "do" )); + } + + public static final CommandSpec call_depth = CommandSpec.DO; + + @Command public void call_depth(IPrintWriter out,ScopedInterpreter<IntegerNamespace> interp) { + out.print( interp.getArg(new IntegerNamespace(interp.callDepth()),"do") ); + } + + + public static final CommandSpec _switch = CommandSpec.DO() + .optionalParameters("value") + .build() + ; + + @Command("switch") public void _switch(IPrintWriter out,ScopedInterpreter<SwitchNamespace> interp) { + out.print( interp.getArg(new SwitchNamespace(interp.getArgString("value")),"do") ); + } + + @Namespace ( + name = "switch", + global = false, + transparent = true + ) + public static final class SwitchNamespace { + private final String value; + private boolean isDone = false; + + private SwitchNamespace(String value) { + this.value = value; + } + + @Command public void switch_value(IPrintWriter out,Interpreter interp) { + out.print( value ); + } + + public static final CommandSpec _case = new CommandSpec.Builder() + .parameters("value") + .dotParameter("do") + .outputtedParameters() // to trim surrounding white-space + .build() + ; + + @Command("case") public void _case(IPrintWriter out,Interpreter interp) { + if( !isDone && interp.getArgString("value").equals(value) ) { + out.print( interp.getArg("do") ); + isDone = true; + } + } + + public static final CommandSpec default_case = new CommandSpec.Builder() + .dotParameter("do") + .outputtedParameters("do") + .build() + ; + + @Command public void default_case(IPrintWriter out,Interpreter interp) { + if( !isDone ) { + out.print( interp.getArg("do") ); + isDone = true; + } + } + + public static final CommandSpec regex_case = new CommandSpec.Builder() + .parameters("regex") + .scopedParameters("do") + .dotParameter("do") + .outputtedParameters("do") + .build() + ; + + @Command public void regex_case(IPrintWriter out,ScopedInterpreter<RegexNamespace> interp) { + if( !isDone ) { + Matcher m = Pattern.compile(interp.getArgString("regex")).matcher(value); + if( m.matches() ) { + out.print( interp.getArg(new RegexNamespace(m,value),"do") ); + isDone = true; + } + } + } + + } + + + + @Namespace ( + name = "block", + global = false + ) + public static final class BlockNamespace {} + + private static final BlockNamespace BLOCK = new BlockNamespace(); + + public static final CommandSpec block = CommandSpec.DO; + + @Command public void block(IPrintWriter out,ScopedInterpreter<BlockNamespace> interp) { + out.print( interp.getArg(BLOCK,"do") ); + } + + + + @Namespace ( + name = "counter", + global = false + ) + public static final class CounterNamespace { + private int counter = 0; + + public static final CommandSpec increment = CommandSpec.NO_OUTPUT; + + @Command public void increment(IPrintWriter out,Interpreter interp) { + counter++; + } + + @Command public void value(IPrintWriter out,Interpreter interp) { + out.print(counter); + } + + } + + private Map<String,CounterNamespace> counterMap = null; + + public static final CommandSpec counter = CommandSpec.DO() + .parameters("name") + .build() + ; + + @Command public void counter(IPrintWriter out,ScopedInterpreter<CounterNamespace> interp) { + if( counterMap == null ) + counterMap = new HashMap<String,CounterNamespace>(); + String name = interp.getArgString("name"); + if( name==null ) + throw new NullPointerException("name is required"); + CounterNamespace ns = counterMap.get(name); + if( ns == null ) { + ns = new CounterNamespace(); + counterMap.put(name,ns); + } + out.print( interp.getArg(ns,"do") ); + } + + + public static final CommandSpec compile_template = CommandSpec.NO_OUTPUT() + .parameters("macro","namespaces") + .build() + ; + + @Command public void compile_template(IPrintWriter out,Interpreter interp) + throws ClassNotFoundException, CompileException + { + String macroName = interp.getArgString("macro"); + String namespacesStr = interp.getArgString("namespaces").trim(); + String[] namespaces = namespacesStr.length()==0 ? new String[0] : namespacesStr.split("\\s*,\\s*"); + if( interp.template().program().getTemplate( macroName, namespaces ) == null ) + throw new RuntimeException("macro '"+macroName+"' not found"); + } + + + + + private static final CommandSpec ID = new CommandSpec.Builder() + .parameters("id") + .build(); + + public static final CommandSpec command_exists = ID; + + @Command public void command_exists(IPrintWriter out, Interpreter interp) { + out.print(template.program().getMeaning(interp.getArgString("id")) != null); + } + + public static final CommandSpec command_is_binary = ID; + + @Command public void command_is_binary(IPrintWriter out, Interpreter interp) { + out.print(JavaCommand.isJavaCommandId(interp.getArgString("id"))); + } + + public static final CommandSpec command_name = ID; + + @Command public void command_name(IPrintWriter out, Interpreter interp) { + String id = interp.getArgString("id"); + out.print(Macro.getNameFromId(id)); + } + + public static final CommandSpec command_source_name = ID; + + @Command public void command_source_name(IPrintWriter out, Interpreter interp) { + String id = interp.getArgString("id"); + out.print(Macro.getSourceFromId(id)); + } + + + public static final CommandSpec get_macro_id = new CommandSpec.Builder() + .parameters("macro_name") + .build() + ; + + @Command public void get_macro_id(IPrintWriter out, Interpreter interp) { + String name = interp.getArgString("macro_name"); + Collection<Macro> macros = template.program().getMacrosByName(name); + if( macros.isEmpty() ) + throw new RuntimeException("macro not found"); + if( macros.size() != 1 ) + throw new RuntimeException("macro not unique"); + Macro macro = macros.iterator().next(); + out.print(macro.getId()); + } + + +}