public class Template extends Node.Stream.Filter implements Node.Stream.Functor {
- static Template newTemplate(Servlet.ServletScope servletscope, JSScope scope, String str) {
+ static Template newTemplate(Servlet.ServletScope servletscope, Scope scope, String str) {
try {
File f = new File(str);
if (!f.exists()) f = new File(str + ".xt");
} catch (Exception e) { throw new RuntimeException(e); }
}
- static JSScope copyNodeToScope(Node n, JSScope scope) {
+ static Scope copyNodeToScope(Node n, Scope scope) {
try {
for(int i=0; i<n.numattrs; i++) {
scope.declare(n.attrs[i*2]);
- scope.put(n.attrs[i*2], n.attrs[i*2+1]);
+ scope.put(JSU.S(n.attrs[i*2]), JSU.S(n.attrs[i*2+1]));
}
return scope;
} catch (Exception e) { throw new RuntimeException(e); }
private class JSRewriter extends Node.Stream {
private Node.Stream in;
- private JSScope scope;
- public JSRewriter(Node.Stream in, JSScope scope) { this.in = in; this.scope = scope; }
+ private Scope scope;
+ public JSRewriter(Node.Stream in, Scope scope) { this.in = in; this.scope = scope; }
protected boolean _read(Node n) { if (!in.read(n)) return false; transform(n, scope); return true; }
}
- public static Node transform(Node n, JSScope scope) {
- if (n.cdata != null) n.cdata = eval(n.cdata, scope).toString();
- else for(int i=1; i<n.numattrs*2; i+=2) n.attrs[i] = eval(n.attrs[i], scope).toString();
- return n;
+ public static Node transform(Node n, Scope scope) {
+ try {
+ if (n.cdata != null) n.cdata = eval(n.cdata, scope).toString();
+ else for(int i=1; i<n.numattrs*2; i+=2) n.attrs[i] = eval(n.attrs[i], scope).toString();
+ return n;
+ } catch (JSExn e) { throw new RuntimeException(e); }
}
- private static Object eval(String s, JSScope scope) {
+ private static Object eval(String s, Scope scope) throws JSExn {
if (s == null) return null;
StringBuffer ret = new StringBuffer();
for(boolean first = true; s.indexOf("${") != -1; first = false) {
ret.append(s.substring(0, s.indexOf("${")));
String s2 = s.substring(s.indexOf("${")+2);
- Object app = exec("return (" + s2.substring(0, s2.indexOf('}')) + ");\n", scope);
+ JS app = exec("return (" + s2.substring(0, s2.indexOf('}')) + ");\n", scope);
s = s.substring(s.indexOf('}') + 1);
//if (first && s.trim().length() == 0) return app;
- if (!(app == null || app instanceof String || app instanceof Number || app instanceof Boolean))
+ if (!(app == null || app instanceof JSPrimitive))
throw new RuntimeException("javascripts within ${...} can only return strings, numbers, and booleans; not a " +
app.getClass().getName());
- ret.append(app == null ? "null" : app.toString());
+ ret.append(app == null ? "null" : JSU.toString(app));
}
ret.append(s);
return ret.toString();
}
- public static Object exec(String s, JSScope scope) {
+ public static JS exec(String s, Scope scope) {
try {
- return JS.eval(JS.cloneWithNewParentScope(JS.fromReader("input", 0, new StringReader(s)), scope));
+ return JSU.cloneWithNewGlobalScope(JSU.fromReader("input", 0, new StringReader(s)), scope).call(null,null);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
- private JSScope scope;
+ private Scope scope;
private Servlet.ServletScope servletscope;
private Node.Stream children;
public Node.Stream wrap(Node.Stream children) { this.children = children; return this; }
- public Template(Servlet.ServletScope servletscope, JSScope scope, Reader template) {
+ public Template(Servlet.ServletScope servletscope, JS scope, Reader template) {
super(new Node.Stream.FromXML(template));
- this.scope = scope;
+ this.scope = new Scope(scope);
this.servletscope = servletscope;
}
public boolean _read(Node n) { boolean ret = __read(n); if (ret) transform(n, scope); return ret; }
public boolean __read(final Node n) {
if (!upstreamRead(n)) return false;
if (n.cdata != null) return true;
- final String uri = n.uri;
+ String uri = n.uri;
+ if (uri == null) uri = "http://www.w3.org/1999/xhtml"; // FIXME FIXME FIXME!!!!
final String name = n.name;
if (uri.indexOf(':') == -1)
throw new RuntimeException("uri does not contain a colon: " + uri + " (tag name " + name + ")");
final String rest = uri.substring(uri.indexOf(':')+1);
if (uri.equals("http://www.w3.org/1999/xhtml")) { return true;
} else if (method.equals("webinf")) {
- return graft(newTemplate(servletscope, copyNodeToScope(transform(n, scope), new JSScope(servletscope)),
+ return graft(newTemplate(servletscope, copyNodeToScope(transform(n, scope), new Scope(servletscope)),
servletscope.getRealPath("/") + "/WEB-INF/" + rest + name), n).upstreamRead(n);
+ } else if (uri.equals("http://xt.ibex.org/form")) {
+ return graft(new InputTag(n.name), n).upstreamRead(n);
} else if (uri.equals("http://xt.ibex.org/")) {
//#switch(name)
+ case "form": return graft(new FormTag(n.attr("class")), n).upstreamRead(n);
+ case "input": return graft(new InputTag(n.attr("field")), n).upstreamRead(n);
case "if":
transform(n, scope);
- return graft("true".equals(n.attr("if")) ? new DropTag() : new DropAll(), n).upstreamRead(n);
+ return graft((Node.Stream.Functor)("true".equals(n.attr("if"))?new DropTag():new DropAll()), n).upstreamRead(n);
case "js": return graft(new JsTag(scope), n).upstreamRead(n);
+ case "wiki": return graft(new WikiTag(n, scope), n).upstreamRead(n);
case "foreach": return graft(new ForEach(n, scope), n).upstreamRead(n);
case "children":
if (children == null) return true;
private class ForEach extends Node.Stream.Filter implements Node.Stream.Functor {
private Node[] nodes = null;
private Vec array = new Vec();
- private JSScope scope;
- public ForEach(Node n, JSScope s) {
+ private Scope scope;
+ public ForEach(Node n, Scope s) {
super(Node.Stream.NULL);
- Vec v = ((JSArray)exec("return (" + n.attr("in").toString() + ");", this.scope = s)).toVec();
- while(true) { Object o = v.pop(); if (o == null) break; array.push(o); }
+ try {
+ JSArray a = ((JSArray)exec("return (" + n.attr("in").toString() + ");", this.scope = s));
+ while(true) {
+ JS o = a.call(JSU.S("pop"), new JS[] { });
+ System.out.println("called pop on a "+a.getClass().getName()+" of length " +a.size()+" , got " + (o==null ? null : o.getClass().getName()));
+ if (o == null) break;
+ array.push(o);
+ }
+ } catch (JSExn e) {
+ throw new RuntimeException(e);
+ }
}
public Node.Stream wrap(Node.Stream kids) {
Vec nodes = new Vec();
protected boolean _read(Node n) {
if (upstreamRead(n)) return true;
if (array.size() == 0) return false;
- JSScope scope2 = new JSScope(scope);
- try { scope2.declare("x"); scope2.put("x", array.pop()); } catch (JSExn e) { throw new RuntimeException(e); }
+ Scope scope2 = new Scope(scope);
+ try { scope2.declare("x"); scope2.put(JSU.S("x"), (JS)array.pop()); } catch (JSExn e) { throw new RuntimeException(e); }
return graft(new ConstantFunctor(new JSRewriter(new Node.Stream() {
private int i = 0;
protected boolean _read(Node n) {
}
}
+ private class WikiTag implements Node.Stream.Functor {
+ public WikiTag(Node n, Scope s) { }
+ public Node.Stream wrap(final Node.Stream kids) {
+ return new Node.Stream() {
+ public boolean _read(Node n) {
+ if (!kids.read(n)) return false;
+ System.out.println("kids.cdata == " + n.cdata);
+ if (n.cdata == null) return true;
+
+ // FIXME: links, code, and math
+ n.cdata = n.cdata.replaceAll("__([^_]+)__", "<u>$1</u>");
+ n.cdata = n.cdata.replaceAll("\\~\\~([^\\~]+)\\~\\~", "<i>$1</i>");
+ n.cdata = n.cdata.replaceAll("\\*\\*([^\\*]+)\\*\\*", "<b>$1</b>");
+ n.cdata = n.cdata.replaceAll("==([^=]+)==", "<h2>$1</h2>");
+ n.cdata = n.cdata.replaceAll("=<h2>([^=]+)</h2>=", "<h3>$1</h3>");
+ n.cdata = n.cdata.replaceAll("=<h3>([^=]+)</h3>=", "<h4>$1</h4>");
+ n.cdata = n.cdata.replaceAll("(\n|\r\n)[ ]*(\n|\r\n)", "\n<br/><br/>\n");
+ return true;
+ } };
+ }
+ }
+
+ private class InputTag implements Node.Stream.Functor {
+ final String fieldName;
+ public InputTag(String fieldName) { this.fieldName = fieldName; }
+ public Node.Stream wrap(Node.Stream kids) {
+ try {
+ return new Node.Stream.FromXML(new StringReader(servletscope.currentForm.emit(fieldName)));
+ } catch (Exception e) { Log.warn(this, e); return null; }
+ }
+ }
+
+ private class FormTag implements Node.Stream.Functor {
+ final String classname;
+ public FormTag(String classname) { this.classname = classname; }
+ public Node.Stream wrap(final Node.Stream kids) {
+ try {
+ servletscope.currentForm = (Form)Class.forName(classname).newInstance();
+ Log.warn("emit", servletscope.currentForm.emit());
+ return new Node.Stream() {
+ boolean done = false;
+ public boolean _read(Node n) {
+ if (done) return kids._read(n);
+ done = true;
+ n.clear();
+ n.name = "form";
+ n.uri = "http://www.w3.org/1999/xhtml";
+ n.numattrs = 1;
+ n.attrs = new String[] { "action", "/servlet/"+classname };
+ return true;
+ }
+ };
+ } catch (Exception e) {
+ Log.warn(this, e);
+ return null;
+ }
+ } }
+
private class DropTag implements Node.Stream.Functor {
public Node.Stream wrap(Node.Stream kids) {
return kids;
} }
private class JsTag implements Node.Stream.Functor {
- JSScope scope;
- public JsTag(JSScope scope) { this.scope = scope; }
+ Scope scope;
+ public JsTag(Scope scope) { this.scope = scope; }
public Node.Stream wrap(final Node.Stream s) {
return new Node.Stream() {
protected boolean _read(Node n) {