f677f286824051240bd7c76f7f57f39b06bf460b
[org.ibex.xt-crawshaw.git] / src / java / org / ibex / xt / shell / Shell.java
1 package org.ibex.xt.shell;
2
3 import java.io.*;
4 import java.net.*;
5
6 import org.ibex.js.*;
7 import org.ibex.util.*;
8
9 public class Shell {
10
11     public static void main(String[] args) throws Exception {
12         if (args.length == 0 || args.length > 2||  !args[0].startsWith("http://")) {
13             printUsage(); return;
14         }
15         Shell shell = new Shell(new URL(args[0]));
16
17         if (args.length == 2) {
18             // FIXME
19         } else {
20             shell.listen(new InputStreamReader(System.in), new OutputStreamWriter(System.out));
21         }
22     }
23
24     private static void printUsage() {
25         System.out.println("Usage: xish url [command]");
26     }
27
28
29     /** Supported commands. */
30     private Command[] commands;
31
32     /** Root context. */
33     private final JS root;
34
35     /** Current JS context for the shell. */
36     private JS scope;
37
38     /** Current path to <tt>scope</tt> in <tt>root</tt>. */
39     private Object[] path;
40
41     /** Returns the object represented by the given path,
42      *  ignoring the current shell path context.*/
43     public Object getFromPath(Object[] path) throws NoSuchPathException, JSExn {
44         if (path.length == 0) return root;
45
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());
51             }
52             return root.get(sb.toString());
53         } else {
54             JS cur = root;
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.NoSuchPathException();
58                 cur = (JS)o;
59             }
60             return cur.get(path[path.length - 1]);
61         }
62     }
63
64     /** Set the current path of the shell, modifiying the result of getScope(). */
65     public void setPath(Object[] s) throws NoSuchPathException {
66         JS cur = root;
67         if (s == null) s = new Object[0];
68         for (int i=0; i < s.length; i++) {
69             Object o;
70             try { o = cur.get(s[i]); } catch (JSExn e) { throw new NoSuchPathException(); }
71             if (o == null || !(o instanceof JS)) throw new NoSuchPathException();
72             cur = (JS)o;
73         }
74         scope = cur;
75         path = s;
76     }
77
78     /** Returns the current path of the shell. */
79     public Object[] getPath() { return path; }
80
81     /** Returns String represntation of path, using '/' as a seperator. */
82     public String getPathAsString() {
83         if (path.length == 0) return "/";
84         StringBuffer sb = new StringBuffer();
85         for (int i=0; i < path.length; i++) {
86             sb.append('/'); sb.append(path[i].toString());
87         }
88         return sb.toString();
89     }
90
91     /** Returns the context matching the current path. */
92     public JS getScope() { return scope; }
93
94     /** Returns the context matching the current path. */
95     public JS getRootScope() { return root; }
96
97     /** Returns all supported commands. */
98     public Command[] getCommands() { return commands; }
99
100     /** Returns the command matching the given name. */
101     public Command getCommand(String name) {
102         for (int i=0; i < commands.length; i++)
103             if (commands[i].name().equals(name)) return commands[i];
104         return null;
105     }
106
107     /** Create a new Shell using the given url for the server. */
108     public Shell(URL url) {
109         root = scope = new JSRemote(url);
110         path = new String[0];
111         commands = new Command[] {
112             new Command.Ls(this),
113             new Command.Pwd(this),
114             new Command.Cd(this),
115             new Command.Rm(this),
116             new Command.Help(this)
117         };
118     }
119
120     public void listen(Reader r, Writer w) throws IOException {
121         LineNumberReader in = new LineNumberReader(r);
122         PrintWriter out = new PrintWriter(w);
123
124         out.println("ibex xt shell: type help or exit");
125         out.print("xt:"); out.print(getPathAsString()); out.print("# ");
126         out.flush();
127
128         String line;
129         String buffer = "";
130         int countBraceOpen = 0, countBraceClose = 0;
131         int countBracketOpen = 0, countBracketClose = 0;
132         int countSQBracketOpen = 0, countSQBracketClose = 0;
133         while ((line = in.readLine()) != null) {
134             if (line.length() > 0) {
135                 if (line.startsWith("exit")) return;
136
137                 for (int i=0; i < line.length(); i++) {
138                     switch (line.charAt(i)) {
139                         case '{': countBraceOpen++; break;
140                         case '}': countBraceClose++; break;
141                         case '(': countBracketOpen++; break;
142                         case ')': countBracketClose++; break;
143                         case '[': countSQBracketOpen++; break;
144                         case ']': countSQBracketClose++; break;
145                     }
146                 }
147
148                 boolean nonendchar = line.charAt(line.length() - 1) == '\\';
149                 if (nonendchar) line = line.substring(0, line.length() - 1);
150                 buffer += line;
151
152                 if (nonendchar ||
153                         countBracketOpen != countBracketClose ||
154                         countBraceOpen != countBraceClose ||
155                         countSQBracketOpen != countSQBracketClose) {
156                     out.print('>');
157                     out.flush(); continue;
158                 }
159             }
160
161             if (buffer.length() > 0) {
162                 String[] c = buffer.split(" ");
163                 Command cmd = getCommand(c[0]);
164
165                 if (cmd == null) {
166                     out.write(c[0]);
167                     w.write(": command not found\n");
168                 } else cmd.execute(out, c);
169
170                 buffer = "";
171             }
172             out.print("xt:"); out.print(getPathAsString()); out.print("# ");
173             out.flush();
174         }
175     }
176
177     public static class NoSuchPathException extends Exception {}
178 }