--- old/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/EditObject.java 2015-08-27 14:14:52.004332400 +0530 +++ new/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/EditObject.java 2015-08-27 14:14:51.654331900 +0530 @@ -45,16 +45,16 @@ props = Collections.unmodifiableSet(s); } + private final Console console; private final Consumer errorHandler; private final Consumer evaluator; - private final Console console; private String editor; - EditObject(final Consumer errorHandler, final Consumer evaluator, - final Console console) { + EditObject(final Console console, final Consumer errorHandler, + final Consumer evaluator) { + this.console = console; this.errorHandler = errorHandler; this.evaluator = evaluator; - this.console = console; } @Override --- old/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/HistoryObject.java 2015-08-27 14:14:54.164335400 +0530 +++ new/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/HistoryObject.java 2015-08-27 14:14:53.804334900 +0530 @@ -25,10 +25,15 @@ package jdk.nashorn.tools.jjs; +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; import java.io.IOException; +import java.io.PrintWriter; import java.util.Collections; import java.util.HashSet; import java.util.Set; +import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; import jdk.internal.jline.console.history.FileHistory; @@ -36,6 +41,7 @@ import jdk.nashorn.api.scripting.AbstractJSObject; import jdk.nashorn.api.scripting.JSObject; import jdk.nashorn.internal.runtime.JSType; +import static jdk.nashorn.internal.runtime.ECMAErrors.typeError; import static jdk.nashorn.internal.runtime.ScriptRuntime.UNDEFINED; /* @@ -47,16 +53,51 @@ final HashSet s = new HashSet<>(); s.add("clear"); s.add("forEach"); + s.add("load"); s.add("print"); + s.add("save"); s.add("size"); s.add("toString"); props = Collections.unmodifiableSet(s); } private final FileHistory hist; + private final PrintWriter err; + private final Consumer evaluator; - HistoryObject(final FileHistory hist) { + HistoryObject(final FileHistory hist, final PrintWriter err, + final Consumer evaluator) { this.hist = hist; + this.err = err; + this.evaluator = evaluator; + } + + @Override + public boolean isFunction() { + return true; + } + + @Override + public Object call(final Object thiz, final Object... args) { + if (args.length > 0) { + int index = JSType.toInteger(args[0]); + if (index < 0) { + index += (hist.size() - 1); + } else { + index--; + } + + if (index >= 0 && index < (hist.size() - 1)) { + final CharSequence src = hist.get(index); + hist.replace(src); + err.println(src); + evaluator.accept(src.toString()); + } else { + hist.removeLast(); + err.println("no history entry @ " + (index + 1)); + } + } + return UNDEFINED; } @Override @@ -66,8 +107,12 @@ return (Runnable)hist::clear; case "forEach": return (Function)this::iterate; + case "load": + return (Consumer)this::load; case "print": return (Runnable)this::print; + case "save": + return (Consumer)this::save; case "size": return hist.size(); case "toString": @@ -98,9 +143,32 @@ return props; } + private void save(final Object obj) { + final File file = getFile(obj); + try (final PrintWriter pw = new PrintWriter(file)) { + for (History.Entry e : hist) { + pw.println(e.value()); + } + } catch (final IOException exp) { + throw new RuntimeException(exp); + } + } + + private void load(final Object obj) { + final File file = getFile(obj); + String item = null; + try (final BufferedReader r = new BufferedReader(new FileReader(file))) { + while ((item = r.readLine()) != null) { + hist.add(item); + } + } catch (final IOException exp) { + throw new RuntimeException(exp); + } + } + private void print() { for (History.Entry e : hist) { - System.out.println(e.value()); + System.out.printf("%3d %s\n", e.index() + 1, e.value()); } } @@ -112,4 +180,17 @@ } return UNDEFINED; } + + private static File getFile(final Object obj) { + File file = null; + if (obj instanceof String) { + file = new File((String)obj); + } else if (obj instanceof File) { + file = (File)obj; + } else { + throw typeError("not.a.file", JSType.toString(obj)); + } + + return file; + } } --- old/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Main.java 2015-08-27 14:14:56.254338300 +0530 +++ new/src/jdk.scripting.nashorn.shell/share/classes/jdk/nashorn/tools/jjs/Main.java 2015-08-27 14:14:55.914337800 +0530 @@ -33,6 +33,7 @@ import java.io.IOException; import java.io.OutputStream; import java.io.PrintWriter; +import java.util.function.Consumer; import jdk.internal.jline.console.completer.Completer; import jdk.internal.jline.console.UserInterruptException; import jdk.nashorn.api.scripting.NashornException; @@ -116,26 +117,27 @@ global.addShellBuiltins(); if (System.getSecurityManager() == null) { + final Consumer evaluator = str -> { + // could be called from different thread (GUI), we need to handle Context set/reset + final Global _oldGlobal = Context.getGlobal(); + final boolean _globalChanged = (oldGlobal != global); + if (_globalChanged) { + Context.setGlobal(global); + } + try { + evalImpl(context, global, str, err, env._dump_on_error); + } finally { + if (_globalChanged) { + Context.setGlobal(_oldGlobal); + } + } + }; + // expose history object for reflecting on command line history - global.addOwnProperty("history", Property.NOT_ENUMERABLE, new HistoryObject(in.getHistory())); + global.addOwnProperty("history", Property.NOT_ENUMERABLE, new HistoryObject(in.getHistory(), err, evaluator)); // 'edit' command - global.addOwnProperty("edit", Property.NOT_ENUMERABLE, new EditObject(err::println, - str -> { - // could be called from different thread (GUI), we need to handle Context set/reset - final Global _oldGlobal = Context.getGlobal(); - final boolean _globalChanged = (oldGlobal != global); - if (_globalChanged) { - Context.setGlobal(global); - } - try { - evalImpl(context, global, str, err, env._dump_on_error); - } finally { - if (_globalChanged) { - Context.setGlobal(_oldGlobal); - } - } - }, in)); + global.addOwnProperty("edit", Property.NOT_ENUMERABLE, new EditObject(in, err::println, evaluator)); } while (true) {