package org.ibex.xt.shell;
-import java.util.*;
-
+import java.io.StringReader;
import java.io.Writer;
import java.io.IOException;
+import java.util.*;
+
+import org.ibex.js.*;
+
public abstract class Command {
/** Returns the command name. */
public abstract String name();
public String help() { return "Print the path to the current object."; }
public void execute(Writer w, String[] c, Env env) throws IOException {
if (c.length != 1) { w.write(usage()); return; }
- w.write(env.path.equals("") ? "/" : env.path.replace('.', '/'));
+ w.write(env.path.equals("") ? "." : env.path);
w.write("\n");
}
}
public String help() { return
"Chnages the current object that all other commands use "+
"as the base for running.\n Pass either a relative path "+
- "(e.g. in /prevalent, type cd myob, now in /prevalent/myob) "+
- "or an absolute path (e.g. cd /prevalent/myob).\n\n" +
+ "(e.g. in .prevalent, type cd myob, now in .prevalent.myob) "+
+ "or an absolute path (e.g. cd .prevalent.myob).\n\n" +
"To go up one level, cd .. can be used.";
}
public void execute(Writer w, String[] c, Env env) throws IOException {
if (c.length > 2) w.write(usage());
- else if (c.length == 1 || c[1].equals("") || c[1].equals("/")) env.path = "";
+ else if (c.length == 1 || c[1].equals("") || c[1].equals(".")) env.path = "";
else if (c[1].equals("..")) {
String n = env.path;
n = n.substring(0, n.lastIndexOf('.'));
}
}
}
+ }
+ }
+
+ public static class Set extends Command {
+ public String name() { return "set"; }
+ public String usage() { return "[name] [object]"; }
+ public String summary() { return "Sets ."; }
+ public String help() { return "Removes objects."; } // FIXME
+
+ public void execute(Writer w, String[] c, Env env) throws IOException {
+ if (c.length < 3) { w.write(usage()); }
+
+ String m = c[1];
+ String s = "return (";
+ for (int i=2; i < c.length; i++) s += c[i];
+ s += ");";
+ JS js;
+ try { js = JS.fromReader("input", 0, new StringReader(s)); }
+ catch (IOException e) {
+ w.write("error: ");
+ w.write(e.getMessage());
+ w.write("\n");
+ return;
+ }
- // Object ret = send(new KeyRequest( FIXME: CompositeRequest
+ Request.Response ret = env.send(new Request.SetKey(env.path, m, js));
}
}
-
}
/** Returns a path, based on console-style representation. */
public String path(String c) {
- if (c.equals("") || c.equals(".") || c.equals("/")) {
+ if (c.equals("") || c.equals(".")) {
c = ".";
} else if (c.equals("..")) {
+ c = path;
c = c.substring(0, c.lastIndexOf('.'));
if (c.equals("")) c = ".";
} else {
- if (c.charAt(0) != '/') c = path + "." + c;
- c = c.replaceAll("/+", ".");
+ if (c.charAt(0) != '.') c = path + "." + c;
if (c.length() > 1 && c.charAt(c.length() - 1) == '.')
c = c.substring(0, c.length() - 1);
}
}
}
+ public static class SetKey extends Key {
+ protected JS value;
+ public SetKey() {}
+ public SetKey(String p, String m, JS val) { super(p, m); this.value = val; }
+
+ public Response process(JSScope root) throws JSExn {
+ JS js = keyed(path(root));
+ if (js == null) throw new JSExn("no such path");
+
+ js.put(matcher, JS.eval(JS.cloneWithNewParentScope(
+ value, new JSResolve(root, js))));
+ return new Res(); // TODO: return put() value when it has one
+ }
+
+ public class Res extends Response {
+ }
+
+ public class JSResolve extends JSScope {
+ private JS path;
+ public JSResolve(JSScope parent, JS path) { super(parent); this.path = path; }
+ public Object get(Object key) throws JSExn {
+ if (key != null && key instanceof String) {
+ String k = (String)key;
+ if (k.startsWith(".")) k = k.substring(1);
+ else return path.get(k);
+ }
+ return super.get(key);
+ }
+ public void put(Object key, Object val) throws JSExn {
+ if (key != null && key instanceof String) {
+ String k = (String)key;
+ if (k.startsWith(".")) k = k.substring(1);
+ else { path.put(key, val); return; }
+ }
+ super.put(key, val);
+ }
+ }
+ }
+
/** Runs a series of requests. */
public static class Composite extends Request {
private boolean breakOnError = false;
new Command.Pwd(),
new Command.Cd(),
new Command.Rm(),
+ new Command.Set(),
new Command.Help()
};
}
String line;
String buffer = "";
+ int countBraceOpen = 0, countBraceClose = 0;
+ int countBracketOpen = 0, countBracketClose = 0;
+ int countSQBracketOpen = 0, countSQBracketClose = 0;
while ((line = in.readLine()) != null) {
if (line.length() > 0) {
if (line.startsWith("exit")) return;
- if (line.charAt(line.length() - 1) == '\\') {
- buffer += line.substring(0, line.length() - 1);
- out.print('>');
- out.flush(); continue;
+
+ for (int i=0; i < line.length(); i++) {
+ switch (line.charAt(i)) {
+ case '{': countBraceOpen++; break;
+ case '}': countBraceClose++; break;
+ case '(': countBracketOpen++; break;
+ case ')': countBracketClose++; break;
+ case '[': countSQBracketOpen++; break;
+ case ']': countSQBracketClose++; break;
+ }
}
+ boolean nonendchar = line.charAt(line.length() - 1) == '\\';
+ if (nonendchar) line = line.substring(0, line.length() - 1);
buffer += line;
+
+ if (nonendchar ||
+ countBracketOpen != countBracketClose ||
+ countBraceOpen != countBraceClose ||
+ countSQBracketOpen != countSQBracketClose) {
+ out.print('>');
+ out.flush(); continue;
+ }
}
if (buffer.length() > 0) {