/** * Copyright 2013 Douglas Campos, and individual contributors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.dynjs.cli; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.io.PrintWriter; import org.dynjs.exception.DynJSException; import org.dynjs.runtime.DynJS; import org.jboss.aesh.console.AeshConsoleCallback; import org.jboss.aesh.console.Console; import org.jboss.aesh.console.ConsoleOperation; import org.jboss.aesh.console.Prompt; import org.jboss.aesh.console.settings.QuitHandler; import org.jboss.aesh.console.settings.Settings; import org.jboss.aesh.console.settings.SettingsBuilder; public class Repl { public static final String WELCOME_MESSAGE = "dynjs console." + System.lineSeparator() + "Type exit and press ENTER to leave." + System.lineSeparator(); public static final String PROMPT = "dynjs> "; private final DynJS runtime; private final PrintStream out; private final InputStream in; private final String welcome; private final String prompt; private PrintWriter log; public Repl(DynJS runtime, InputStream in, OutputStream out) { this(runtime, in, out, WELCOME_MESSAGE, PROMPT); } public Repl(DynJS runtime, InputStream in, OutputStream out, String welcome, String prompt) { this(runtime, in, out, welcome, prompt, System.getProperty("user.dir") + "/dynjs.log"); } public Repl(DynJS runtime, InputStream in, OutputStream out, String welcome, String prompt, String log) { this.prompt = prompt; this.welcome = welcome; this.runtime = runtime; this.out = new PrintStream(out); this.in = in; try { this.log = new PrintWriter(log); } catch (IOException e) { System.err.println("Cannot create error log " + log); } } public void run() { final Settings consoleSettings = new SettingsBuilder() .outputStream(this.out) .inputStream(this.in) .historySize(100) .parseOperators(false) .quitHandler(new QuitHandler() { @Override public void quit() { if (log != null) { log.close(); } } }).create(); final Console console = new Console(consoleSettings); console.getShell().out().println(welcome); console.setPrompt(new Prompt(prompt)); console.setConsoleCallback(new AeshConsoleCallback() { @Override public int execute(ConsoleOperation output) { String statement = output.getBuffer(); log.write(statement + "\n"); if (statement.equalsIgnoreCase("exit")) { console.stop(); return 0; } else { try { Object object = runtime.evaluate(statement); log.write(object.toString() + "\n"); console.getShell().out().println(object.toString()); } catch (DynJSException e) { console.getShell().out().println(e.getLocalizedMessage()); logException(e); } catch (IncompatibleClassChangeError e) { console.getShell().err().println("ERROR> " + e.getLocalizedMessage()); console.getShell().err().println("Error parsing statement: " + statement); logException(e); } catch (Exception e) { e.printStackTrace(new PrintWriter(out)); logException(e); } } return 0; } }); console.start(); } private void logException(Throwable e) { log.write(e.getLocalizedMessage() + "\n"); e.printStackTrace(log); log.write("\n"); } }