1 package org.ibex.xt.shell;
7 import org.ibex.util.*;
11 public static void main(String[] args) throws Exception {
12 if (args.length == 0 || args.length > 2|| !args[0].startsWith("http://")) {
15 Shell shell = new Shell(new URL(args[0]));
17 if (args.length == 2) {
20 shell.listen(new InputStreamReader(System.in), new OutputStreamWriter(System.out));
24 private static void printUsage() {
25 System.out.println("Usage: xish url [command]");
29 /** Supported commands. */
30 private Command[] commands;
33 private final JS root;
35 /** Current JS context for the shell. */
38 /** Current path to <tt>scope</tt> in <tt>root</tt>. */
39 private Object[] path;
41 /** Returns the object represented by the given path,
42 * ignoring the current shell path context.*/
43 public Object getFromPath(Object[] path) throws BadPathException, JSExn {
44 if (path.length == 0) return root;
46 if (root instanceof JSRemote) {
47 // JSRemote will automatically process its keys for '.' seperators
48 StringBuffer sb = new StringBuffer(path[0].toString());
49 for (int i=1; i < path.length; i++) {
50 sb.append('.'); sb.append(path[i].toString());
52 return root.get(sb.toString());
55 for (int i=0; i < path.length - 1; i++) {
56 Object o = cur.get(path[i]);
57 if (o == null || !(o instanceof JS)) throw new Shell.BadPathException();
60 return cur.get(path[path.length - 1]);
64 public void transaction(JS t) {
65 if (root instanceof JSRemote) {
66 ((JSRemote)root).transaction(
67 JS.cloneWithNewParentScope(t, new JSScope(null)));
69 // FIXME JS.eval(JS.cloneWithNewParentScope(t, root));
73 /** Set the current path of the shell, modifiying the result of getScope(). */
74 public void setPath(Object[] s) throws BadPathException {
76 if (s == null) s = new Object[0];
77 for (int i=0; i < s.length; i++) {
79 try { o = cur.get(s[i]); } catch (JSExn e) { throw new BadPathException(); }
80 if (o == null || !(o instanceof JS)) throw new BadPathException();
87 /** Returns the current path of the shell. */
88 public Object[] getPath() { return path; }
90 /** Returns String represntation of path, using '/' as a seperator. */
91 public String getPathAsString() {
92 if (path.length == 0) return "/";
93 StringBuffer sb = new StringBuffer();
94 for (int i=0; i < path.length; i++) {
95 sb.append('/'); sb.append(path[i].toString());
100 /** Returns the context matching the current path. */
101 public JS getScope() { return scope; }
103 /** Returns the context matching the current path. */
104 public JS getRootScope() { return root; }
106 /** Returns all supported commands. */
107 public Command[] getCommands() { return commands; }
109 /** Returns the command matching the given name. */
110 public Command getCommand(String name) {
111 for (int i=0; i < commands.length; i++)
112 if (commands[i].name().equals(name)) return commands[i];
116 /** Create a new Shell using the given url for the server. */
117 public Shell(URL url) {
118 root = scope = new JSRemote(url);
119 path = new String[0];
120 commands = new Command[] {
121 new Command.Ls(this),
122 new Command.Pwd(this),
123 new Command.Cd(this),
124 new Command.Rm(this),
125 new Command.Replace(this),
126 new Command.Mkdir(this),
127 new Command.Help(this)
131 public void listen(Reader r, Writer w) throws IOException {
132 LineNumberReader in = new LineNumberReader(r);
133 PrintWriter out = new PrintWriter(w);
135 out.println("ibex xt shell: type help or exit");
136 out.print("xt:"); out.print(getPathAsString()); out.print("# ");
141 int countBraceOpen = 0, countBraceClose = 0;
142 int countBracketOpen = 0, countBracketClose = 0;
143 int countSQBracketOpen = 0, countSQBracketClose = 0;
144 while ((line = in.readLine()) != null) {
145 if (line.length() > 0) {
146 if (line.startsWith("exit")) return;
148 for (int i=0; i < line.length(); i++) {
149 switch (line.charAt(i)) {
150 case '{': countBraceOpen++; break;
151 case '}': countBraceClose++; break;
152 case '(': countBracketOpen++; break;
153 case ')': countBracketClose++; break;
154 case '[': countSQBracketOpen++; break;
155 case ']': countSQBracketClose++; break;
159 boolean nonendchar = line.charAt(line.length() - 1) == '\\';
160 if (nonendchar) line = line.substring(0, line.length() - 1);
164 countBracketOpen != countBracketClose ||
165 countBraceOpen != countBraceClose ||
166 countSQBracketOpen != countSQBracketClose) {
168 out.flush(); continue;
172 if (buffer.length() > 0) {
173 String[] c = buffer.split(" ");
174 Command cmd = getCommand(c[0]);
178 w.write(": command not found\n");
179 } else cmd.execute(out, c);
183 out.print("xt:"); out.print(getPathAsString()); out.print("# ");
188 public static class BadPathException extends Exception {
189 public BadPathException() {}
190 public BadPathException(String msg) { super(msg); }