improve ls output
[org.ibex.xt-crawshaw.git] / src / java / org / ibex / xt / shell / Command.java
1 package org.ibex.xt.shell;
2
3 import java.io.StringReader;
4 import java.io.Writer;
5 import java.io.IOException;
6
7 import java.util.*;
8
9 import org.ibex.js.*;
10
11 public abstract class Command {
12     /** Returns the command name. */
13     public abstract String name();
14
15     /** Returns single-line of usage information, eg. <tt>pattern]</tt> */
16     public abstract String usage();
17
18     /** Returns single-line description of command. */
19     public abstract String summary();
20
21     /** Returns multi-line description. */
22     public abstract String help();
23
24     /** Writes result of execution, even if result is an error. */
25     public abstract void execute(Writer w, String[] args, Env env) throws IOException;
26
27     public static class Help extends Command {
28         public String name() { return "help"; }
29         public String usage() { return "[command name]"; }
30         public String summary() { return "Lists available commands."; }
31         public String help() { return ""; }
32
33         public void execute(Writer w, String[] c, Env env) throws IOException {
34             if (c.length > 1) {
35                 Command cmd = env.command(c[1]);
36                 if (c == null) {
37                     w.write("help: ");
38                     w.write(c[1]);
39                     w.write(": command not found\n");
40                 } else {
41                     w.write("usage: ");
42                     w.write(cmd.name());
43                     w.write(" ");
44                     w.write(cmd.usage());
45                     w.write("\n\n");
46                     w.write(cmd.help());
47                     w.write("\n");
48                 }
49             } else {
50                 int len = 3;
51                 for (int i=0; i < env.commands.length; i++)
52                     len = Math.max(env.commands[i].name().length(), len);
53
54                 w.write("Available commands:\n");
55                 for (int i=0; i < env.commands.length; i++) {
56                     Command cmd = env.commands[i];
57                     w.write("  ");
58                     w.write(cmd.name());
59                     for (int j=len - cmd.name().length(); j >= 0; j--) w.write(" ");
60                     w.write(" - ");
61                     w.write(cmd.summary());
62                     w.write("\n");
63                 }
64                 w.write("\nFor usage details, type help [command name].\n");
65             }
66         }
67     }
68
69     public static class Ls extends Command {
70         public String name() { return "ls"; }
71         public String usage() { return "[path]"; }
72         public String summary() { return "List object entries."; }
73         public String help() { return
74             "Lists the keys in an object. Modelled after the UNIX ls command.";
75         }
76
77         public void execute(Writer w, String[] c, Env env) throws IOException {
78             if (c.length > 2) { w.write(usage()); return; }
79             String p = env.path(c.length == 1 ? "*" : c[1]);
80
81             Request.Response ret = env.send(new Request.Key(p));
82             if (!(ret instanceof Request.Key.Res)) {
83                 w.write("error: ");
84                 w.write(ret.error().getMessage());
85                 w.write("\n");
86             } else {
87                 List l = ((Request.Key.Res)ret).keys();
88                 Iterator i = l.iterator(); while (i.hasNext()) {
89                     w.write(i.next().toString());
90                     w.write("\n");
91                 }
92             }
93         }
94     }
95
96     public static class Pwd extends Command {
97         public String name() { return "pwd"; }
98         public String usage() { return ""; }
99         public String summary() { return "Path to current object."; }
100         public String help() { return "Print the path to the current object."; }
101         public void execute(Writer w, String[] c, Env env) throws IOException {
102             if (c.length != 1) { w.write(usage()); return; }
103             w.write(env.path.equals("") ? "." : env.path);
104             w.write("\n");
105         }
106     }
107
108     public static class Cd extends Command {
109         public String name() { return "cd"; }
110         public String usage() { return "[path]"; }
111         public String summary() { return "Change current object."; }
112         public String help() { return
113             "Chnages the current object that all other commands use "+
114             "as the base for running.\n Pass either a relative path "+
115             "(e.g. in .prevalent, type cd myob, now in .prevalent.myob) "+
116             "or an absolute path (e.g. cd .prevalent.myob).\n\n" +
117             "To go up one level, cd .. can be used.";
118         }
119         public void execute(Writer w, String[] c, Env env) throws IOException {
120             if (c.length > 2) w.write(usage());
121             else if (c.length == 1 || c[1].equals("") || c[1].equals(".")) env.path = "";
122             else if (c[1].equals("..")) {
123                 String n = env.path;
124                 n = n.substring(0, n.lastIndexOf('.'));
125                 env.path = n;
126             } else {
127                 String n = env.path(c[1]);
128
129                 Request.Response ret = env.send(new Request.IsKey(n));
130                 if (!(ret instanceof Request.IsKey.Res)) {
131                     w.write("error: ");
132                     w.write(ret.error().getMessage());
133                     w.write("\n");
134                 } else {
135                     if (((Request.IsKey.Res)ret).exists()) {
136                         w.write("error: ");
137                         w.write(c[1]);
138                         w.write(": no such path\n");
139                     } else {
140                         env.path = n;
141                     }
142                 }
143             }
144         }
145     }
146
147     public static class Rm extends Command {
148         public String name() { return "rm"; }
149         public String usage() { return "[options] [path]"; }
150         public String summary() { return "Removes objects."; }
151         public String help() { return "Removes objects."; } // FIXME
152         public void execute(Writer w, String[] c, Env env) throws IOException {
153             if (c.length == 1) { w.write(usage()); }
154
155             Request.Key[] r = new Request.Key[c.length - 1];
156             for (int i=0; i < r.length; i++) r[i] = new Request.RemoveKey(env.path(c[i + 1]));
157
158             Request.Response ret = env.send(new Request.Composite(r, false));
159             if (!(ret instanceof Request.Composite.Res)) {
160                 w.write("error: ");
161                 w.write(ret.error().getMessage());
162                 w.write("\n");
163             } else {
164                 Request.Response[] res = ((Request.Composite.Res)ret).responses();
165                 for (int i=0; i < res.length; i++) {
166                     if (res[i] instanceof Request.RemoveKey.Res) {
167                         boolean rm = ((Request.RemoveKey.Res)res[i]).removed();
168                         if (!rm) {
169                             w.write("error: cannot remove '");
170                             w.write(c[i + 1]);
171                             w.write("': no such key\n");
172                         }
173                     } else {
174                         w.write("error: cannot remove '");
175                         w.write(c[i + 1]);
176                         w.write("': ");
177                         w.write(res[i].error().getMessage());
178                         w.write("\n");
179                     }
180                 }
181             }
182         }
183     }
184
185     public static class Set extends Command {
186         public String name() { return "set"; }
187         public String usage() { return "[name] [object]"; }
188         public String summary() { return "Sets ."; }
189         public String help() { return "Removes objects."; } // FIXME
190
191         public void execute(Writer w, String[] c, Env env) throws IOException {
192             if (c.length < 3) { w.write(usage()); }
193
194             String m = c[1];
195             String s = "return (";
196             for (int i=2; i < c.length; i++) s += c[i];
197             s += ");";
198
199             JS js;
200             try { js = JS.fromReader("input", 0, new StringReader(s)); }
201             catch (IOException e) {
202                 w.write("error: ");
203                 w.write(e.getMessage());
204                 w.write("\n");
205                 return;
206             }
207
208             Request.Response ret = env.send(new Request.SetKey(env.path, m, js));
209         }
210     }
211
212 }