1 46 package groovy.ui; 47 48 import groovy.lang.Binding; 49 import groovy.lang.GroovyShell; 50 import org.codehaus.groovy.control.CompilationFailedException; 51 import org.codehaus.groovy.control.SourceUnit; 52 import org.codehaus.groovy.runtime.InvokerHelper; 53 import org.codehaus.groovy.sandbox.ui.Prompt; 54 import org.codehaus.groovy.sandbox.ui.PromptFactory; 55 import org.codehaus.groovy.syntax.CSTNode; 56 import org.codehaus.groovy.syntax.TokenStream; 57 import org.codehaus.groovy.tools.ErrorReporter; 58 59 import java.io.IOException ; 60 import java.io.InputStream ; 61 import java.io.PrintStream ; 62 import java.util.HashMap ; 63 import java.util.Iterator ; 64 import java.util.Map ; 65 import java.util.Set ; 66 67 78 public class InteractiveShell { 79 private final GroovyShell shell; 80 private final Prompt prompt; 81 private final InputStream in; 82 private final PrintStream out; 83 private final PrintStream err; 84 85 86 89 public static void main(String args[]) { 90 try { 91 final InteractiveShell groovy = new InteractiveShell(); 92 groovy.run(args); 93 } catch (Exception e) { 94 System.err.println("Caught: " + e); 95 e.printStackTrace(); 96 } 97 } 98 99 100 103 public InteractiveShell() { 104 this(System.in, System.out, System.err); 105 } 106 107 108 public InteractiveShell(final InputStream in, final PrintStream out, final PrintStream err) { 109 this(new Binding(), in, out, err); 110 } 111 112 public InteractiveShell(Binding binding, final InputStream in, final PrintStream out, final PrintStream err) { 113 this.in = in; 114 this.out = out; 115 this.err = err; 116 prompt = PromptFactory.buildPrompt(in, out, err); 117 prompt.setPrompt("groovy> "); 118 shell = new GroovyShell(binding); 119 } 120 121 124 127 public void run(String [] args) throws Exception { 128 final String version = InvokerHelper.getVersion(); 129 130 out.println("Lets get Groovy!"); 131 out.println("================"); 132 out.println("Version: " + version + " JVM: " + System.getProperty("java.vm.version")); 133 out.println("Type 'exit' to terminate the shell"); 134 out.println("Type 'help' for command help"); 135 out.println("Type 'go' to execute the statements"); 136 137 int counter = 1; 138 boolean running = true; 139 while (running) { 140 final String command = read(); 143 if (command == null) { 144 close(); 145 break; 146 } 147 148 reset(); 149 150 if (command.length() > 0) { 151 try { 153 shell.evaluate(command, "CommandLine" + counter++ + ".groovy"); 154 } catch (Exception e) { 155 err.println("Exception: " + e.getMessage()); 156 e.printStackTrace(err); 157 new ErrorReporter(e, false).write(err); 158 } catch (Throwable e) { 159 err.println("Unrecoverable Error: " + e.getMessage()); 160 e.printStackTrace(err); 161 new ErrorReporter(e, false).write(err); 162 err.println(">>> exiting"); 163 164 running = false; 166 } 167 } 168 } 169 } 170 171 172 protected void close() { 173 prompt.close(); 174 } 175 176 177 180 181 private StringBuffer accepted = new StringBuffer (); private String pending = null; private int line = 1; 185 private boolean stale = false; 187 private SourceUnit parser = null; private TokenStream stream = null; private Exception error = null; private CSTNode tree = null; 192 193 196 197 protected void reset() { 198 stale = true; 199 pending = null; 200 line = 1; 201 202 parser = null; 203 stream = null; 204 error = null; 205 tree = null; 206 } 207 208 209 217 218 protected String read() { 219 reset(); 220 out.println(""); 221 222 boolean complete = false; 223 boolean done = false; 224 225 while ( !done) { 226 227 230 try { 231 pending = prompt.readLine(); 232 } catch (IOException e) { 233 } 234 235 if (pending == null || (COMMAND_MAPPINGS.containsKey(pending) && ((Integer ) COMMAND_MAPPINGS.get(pending)).intValue() == COMMAND_ID_EXIT)) { 236 return null; } 238 239 if (COMMAND_MAPPINGS.containsKey(pending)) { 241 int code = ((Integer ) COMMAND_MAPPINGS.get(pending)).intValue(); 242 switch (code) { 243 case COMMAND_ID_HELP: 244 displayHelp(); 245 break; 246 247 case COMMAND_ID_DISCARD: 248 reset(); 249 done = true; 250 break; 251 252 case COMMAND_ID_DISPLAY: 253 displayStatement(); 254 break; 255 256 case COMMAND_ID_EXPLAIN: 257 explainStatement(); 258 break; 259 260 case COMMAND_ID_BINDING: 261 displayBinding(); 262 break; 263 264 case COMMAND_ID_EXECUTE: 265 if (complete) { 266 done = true; 267 } else { 268 err.println("statement not complete"); 269 } 270 break; 271 } 272 273 continue; } 275 276 281 freshen(); 282 283 if (pending.trim().equals("")) { 284 accept(); 285 continue; } 287 288 final String code = current(); 289 290 if (parse(code, 1)) { 291 accept(); 292 complete = true; 293 } else if (error == null) { 294 accept(); 295 } else { 296 report(); 297 } 298 299 } 300 301 return accepted(complete); 303 } 304 305 306 310 private String accepted(boolean complete) { 311 if (complete) { 312 return accepted.toString(); 313 } 314 return ""; 315 } 316 317 318 321 private String current() { 322 return accepted.toString() + pending + "\n"; 323 } 324 325 326 329 private void accept() { 330 accepted.append(pending).append("\n"); 331 line += 1; 332 } 333 334 335 338 private void freshen() { 339 if (stale) { 340 accepted.setLength(0); 341 stale = false; 342 } 343 } 344 345 346 349 350 357 private boolean parse(String code, int tolerance) { 358 boolean parsed = false; 359 360 parser = null; 361 stream = null; 362 error = null; 363 tree = null; 364 365 try { 367 parser = SourceUnit.create("groovysh script", code, tolerance); 368 parser.parse(); 369 tree = parser.getCST(); 370 371 378 parsed = true; 379 } 380 381 catch (CompilationFailedException e) { 383 if (parser.getErrorCount() > 1 || !parser.failedWithUnexpectedEOF()) { 384 error = e; 385 } 386 } catch (Exception e) { 387 error = e; 388 } 389 390 return parsed; 391 } 392 393 394 397 398 private void report() { 399 err.println("Discarding invalid text:"); 400 new ErrorReporter(error, false).write(err); 401 } 402 403 406 private static final int COMMAND_ID_EXIT = 0; 407 private static final int COMMAND_ID_HELP = 1; 408 private static final int COMMAND_ID_DISCARD = 2; 409 private static final int COMMAND_ID_DISPLAY = 3; 410 private static final int COMMAND_ID_EXPLAIN = 4; 411 private static final int COMMAND_ID_EXECUTE = 5; 412 private static final int COMMAND_ID_BINDING = 6; 413 414 private static final int LAST_COMMAND_ID = 6; 415 416 private static final String [] COMMANDS = {"exit", "help", "discard", "display", "explain", "execute", "binding"}; 417 418 private static final Map COMMAND_MAPPINGS = new HashMap (); 419 420 static { 421 for (int i = 0; i <= LAST_COMMAND_ID; i++) { 422 COMMAND_MAPPINGS.put(COMMANDS[i], new Integer (i)); 423 } 424 425 427 COMMAND_MAPPINGS.put("quit", new Integer (COMMAND_ID_EXIT)); 428 COMMAND_MAPPINGS.put("go", new Integer (COMMAND_ID_EXECUTE)); 429 } 430 431 private static final Map COMMAND_HELP = new HashMap (); 432 433 static { 434 COMMAND_HELP.put(COMMANDS[COMMAND_ID_EXIT], "exit/quit - terminates processing"); 435 COMMAND_HELP.put(COMMANDS[COMMAND_ID_HELP], "help - displays this help text"); 436 COMMAND_HELP.put(COMMANDS[COMMAND_ID_DISCARD], "discard - discards the current statement"); 437 COMMAND_HELP.put(COMMANDS[COMMAND_ID_DISPLAY], "display - displays the current statement"); 438 COMMAND_HELP.put(COMMANDS[COMMAND_ID_EXPLAIN], "explain - explains the parsing of the current statement"); 439 COMMAND_HELP.put(COMMANDS[COMMAND_ID_EXECUTE], "execute/go - temporary command to cause statement execution"); 440 COMMAND_HELP.put(COMMANDS[COMMAND_ID_BINDING], "binding - shows the binding used by this interactive shell"); 441 } 442 443 444 447 private void displayHelp() { 448 out.println("Available commands (must be entered without extraneous characters):"); 449 for (int i = 0; i <= LAST_COMMAND_ID; i++) { 450 out.println((String ) COMMAND_HELP.get(COMMANDS[i])); 451 } 452 } 453 454 455 458 private void displayStatement() { 459 final String [] lines = accepted.toString().split("\n"); 460 for (int i = 0; i < lines.length; i++) { 461 out.println((i + 1) + "> " + lines[i]); 462 } 463 } 464 465 468 private void displayBinding() { 469 out.println("Avaialble variables in the current binding"); 470 Binding context = shell.getContext(); 471 Map variables = context.getVariables(); 472 Set set = variables.keySet(); 473 if (set.isEmpty()) { 474 out.println("The current binding is empty."); 475 } else { 476 for (Iterator it = set.iterator(); it.hasNext();) { 477 String key = (String ) it.next(); 478 out.println(key + " = " + variables.get(key)); 479 } 480 } 481 } 482 483 484 488 private void explainStatement() { 489 if (parse(accepted(true), 10) || error == null) { 490 out.println("Parse tree:"); 491 out.println(tree); 492 } else { 493 out.println("Statement does not parse"); 494 } 495 } 496 } 497 498 | Popular Tags |