1 package org.ibex.xt.shell;
4 import java.io.IOException;
7 import java.util.regex.*;
10 import org.ibex.util.*;
12 public abstract class Command {
13 protected Shell shell;
15 protected Command(Shell s) { shell = s; }
17 /** Returns the command name. */
18 public abstract String name();
20 /** Returns a single-line of parameter information, eg. <tt>[pattern]</tt> */
21 public abstract String params();
23 /** Returns single-line description of command. */
24 public abstract String summary();
26 /** Returns multi-line description. */
27 public abstract String help();
29 /** Writes result of execution, even if result is an error. */
30 public abstract void execute(Writer w, String[] args) throws IOException;
33 /** Returns single-line of usage information, eg. <tt>usage: ls [pattern]</tt> */
34 public void usage(Writer w) throws IOException {
42 public List fromShellPath(String s) throws Shell.NoSuchPathException {
43 return fromShellPath(s, null);
46 /** Converts a shell path "/foo/etc/../bar" to its component form,
47 * { "foo", "bar" } and loads it into the returned list.
48 * Handles relative positioning to shell.getPath(). */
49 public List fromShellPath(String s, List l) throws Shell.NoSuchPathException {
50 if (s == null) return null;
51 if (l == null) l = new ArrayList();
53 s = s.trim().replace("/+", "/");
54 if (s.charAt(0) != '/') l.addAll(Arrays.asList(shell.getPath()));
56 StringTokenizer st = new StringTokenizer(s, "/");
57 while (st.hasMoreTokens()) {
58 String part = st.nextToken();
59 if (part == null || part.equals("") || part.equals(".")) continue;
60 else if (part.equals("..")) { if (l.size() > 0) l.remove(l.size() - 1); }
67 public static class Help extends Command {
68 public Help(Shell s) { super(s); }
69 public String name() { return "help"; }
70 public String params() { return "[command name]"; }
71 public String summary() { return "Lists available commands."; }
72 public String help() { return ""; }
74 public void execute(Writer w, String[] c) throws IOException {
76 Command cmd = shell.getCommand(c[1]);
80 w.write(": command not found\n");
89 Command[] cmds = shell.getCommands();
90 for (int i=0; i < cmds.length; i++)
91 len = Math.max(cmds[i].name().length(), len);
93 w.write("Available commands:\n");
94 for (int i=0; i < cmds.length; i++) {
95 Command cmd = cmds[i];
98 for (int j=len - cmd.name().length(); j >= 0; j--) w.write(" ");
100 w.write(cmd.summary());
103 w.write("\nFor usage details, type help [command name].\n");
108 public static class Ls extends Command {
109 public Ls(Shell s) { super(s); }
110 public String name() { return "ls"; }
111 public String params() { return "[path]"; }
112 public String summary() { return "List object entries."; }
113 public String help() { return
114 "Lists the keys in an object. Modelled after the UNIX ls command.";
117 public void execute(Writer w, String[] c) throws IOException {
118 if (c.length > 2) { usage(w); return; }
119 String p = c.length == 1 ? "*" : c[1];
120 if (p.endsWith("/")) p += "*";
123 List path = fromShellPath(p);
124 Object key = path.remove(path.size() - 1);
125 Object po = shell.getFromPath(path.toArray());
126 if (po == null || !(po instanceof JS))
127 throw new Shell.NoSuchPathException();
130 if (key instanceof String &&
131 ((String)key).indexOf('*') >= 0) {
132 String last = (String)key;
133 last = last.replaceAll("\\.", "\\.");
134 last = last.replaceAll("\\*", ".*");
135 Pattern pat = Pattern.compile(last);
136 Iterator i = cur.keys().iterator(); while (i.hasNext()) {
138 if (o == null || !(o instanceof String)) continue;
139 String s = (String)o;
140 if (!pat.matcher(s).matches()) continue;
144 } else if (cur.containsKey(key)) {
145 w.write(key.toString());
148 } catch (Shell.NoSuchPathException e) {
149 w.write("error: no such path: ");
153 w.write("error: no such path: ");
156 w.write(e.getMessage());
162 public static class Pwd extends Command {
163 public Pwd(Shell s) { super(s); }
164 public String name() { return "pwd"; }
165 public String params() { return ""; }
166 public String summary() { return "Path to current object."; }
167 public String help() { return "Print the path to the current object."; }
168 public void execute(Writer w, String[] c) throws IOException {
169 if (c.length != 1) { usage(w); return; }
170 Object[] path = shell.getPath();
171 for (int i=0; i < path.length; i++) {
173 w.write(path[i].toString());
175 if (path.length == 0) w.write("/");
180 public static class Cd extends Command {
181 public Cd(Shell s) { super(s); }
182 public String name() { return "cd"; }
183 public String params() { return "[path]"; }
184 public String summary() { return "Change current object."; }
185 public String help() { return
186 "Chnages the current object that all other commands use "+
187 "as the base for running.\n Pass either a relative path "+
188 "(e.g. in .prevalent, type cd myob, now in .prevalent.myob) "+
189 "or an absolute path (e.g. cd .prevalent.myob).\n\n" +
190 "To go up one level, cd .. can be used.";
192 public void execute(Writer w, String[] c) throws IOException {
193 if (c.length > 2) { usage(w); return; }
194 String path = c.length == 1 ? "/" : c[1];
196 try { shell.setPath(fromShellPath(path).toArray()); }
197 catch (Shell.NoSuchPathException e) {
198 w.write("error: no such path: ");
205 public static class Rm extends Command {
206 public Rm(Shell s) { super(s); }
207 public String name() { return "rm"; }
208 public String params() { return "[options] [path]"; }
209 public String summary() { return "Removes objects."; }
210 public String help() { return "Removes objects."; } // FIXME
211 public void execute(Writer w, String[] c) throws IOException {
212 if (c.length == 1) { usage(w); return; }