diff --git a/.vscode/launch.json b/.vscode/launch.json
index aa506d012ad..e5fb91aec1a 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -30,7 +30,8 @@
"request": "launch",
"mainClass": "org.rascalmpl.shell.RascalShell",
"projectName": "rascal",
- "vmArgs": "-Xss80m -Xmx2g -ea"
+ "vmArgs": "-Xss80m -Xmx2g -ea",
+ "console": "integratedTerminal"
},
{
"type": "java",
@@ -38,7 +39,7 @@
"request": "launch",
"mainClass": "org.rascalmpl.shell.RascalShell",
"projectName": "rascal",
- "cwd" : "${workspaceFolder}/../rascal-tutor",
+ "cwd": "${workspaceFolder}/../rascal-tutor",
"vmArgs": "-Xss80m -Xmx2g -ea"
},
{
diff --git a/pom.xml b/pom.xml
index 171cec5cf5b..9ff6ca5d28f 100644
--- a/pom.xml
+++ b/pom.xml
@@ -34,6 +34,7 @@
3
11
0.28.9-BOOT1
+ 3.27.0
@@ -235,6 +236,7 @@
**/org/rascalmpl/test/AllSuiteParallel.java
**/org/rascalmpl/test/library/LibraryLangPaths.java
**/org/rascalmpl/test/value/AllTests.java
+ **/org/rascalmpl/test/repl/*Test.java
**/org/rascalmpl/*Test.java
@@ -331,19 +333,6 @@
false
-
-
- org.fusesource.jansi
- org.rascalmpl.fusesource.jansi
-
- org.fusesource.jansi.internal.*
-
-
-
- jline
- org.rascalmpl.jline
-
-
*:*
@@ -471,10 +460,35 @@
gson
2.11.0
-
- jline
- jline
- 2.14.6
+
+ org.jline
+ jline-reader
+ ${jline.version}
+
+
+ org.jline
+ jline-terminal
+ ${jline.version}
+
+
+ org.jline
+ jline-terminal-jni
+ ${jline.version}
+
+
+ org.jline
+ jline-style
+ ${jline.version}
+
+
+ org.jline
+ jline-console
+ ${jline.version}
+
+
+ org.jline
+ jansi-core
+ ${jline.version}
org.yaml
@@ -563,44 +577,7 @@
shade
-
-
-
- rascal
- org.rascalmpl.shell.RascalShell
- ${project.version}
- http://www.usethesource.io
-
-
-
-
-
- org.fusesource.jansi
- org.rascalmpl.fusesource.jansi
-
- org.fusesource.jansi.internal.*
-
-
-
- jline
- org.rascalmpl.jline
-
-
-
-
- *:*
-
- META-INF/*.SF
- META-INF/*.DSA
- META-INF/*.RSA
-
-
-
-
-
- jline:*
-
-
+ true
diff --git a/src/org/rascalmpl/checker/StaticChecker.java b/src/org/rascalmpl/checker/StaticChecker.java
deleted file mode 100644
index acb755fa842..00000000000
--- a/src/org/rascalmpl/checker/StaticChecker.java
+++ /dev/null
@@ -1,125 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2009-2013 CWI
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Eclipse Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/epl-v10.html
- *
- * Contributors:
- * * Jurgen J. Vinju - Jurgen.Vinju@cwi.nl - CWI
- * * Mark Hills - Mark.Hills@cwi.nl (CWI)
- * * Arnold Lankamp - Arnold.Lankamp@cwi.nl
-*******************************************************************************/
-package org.rascalmpl.checker;
-
-import java.io.OutputStream;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.rascalmpl.debug.IRascalMonitor;
-import org.rascalmpl.exceptions.ImplementationError;
-import org.rascalmpl.interpreter.Configuration;
-import org.rascalmpl.interpreter.Evaluator;
-import org.rascalmpl.interpreter.env.GlobalEnvironment;
-import org.rascalmpl.interpreter.env.ModuleEnvironment;
-import org.rascalmpl.interpreter.load.StandardLibraryContributor;
-import org.rascalmpl.parser.gtd.exception.ParseError;
-import org.rascalmpl.uri.URIUtil;
-import org.rascalmpl.values.ValueFactoryFactory;
-import org.rascalmpl.values.parsetrees.ITree;
-
-import io.usethesource.vallang.ISourceLocation;
-import io.usethesource.vallang.IValue;
-import io.usethesource.vallang.IValueFactory;
-import io.usethesource.vallang.type.Type;
-import io.usethesource.vallang.type.TypeStore;
-
-public class StaticChecker {
- private final Evaluator eval;
- public static final String TYPECHECKER = "typecheckTree";
- private boolean checkerEnabled;
- private boolean initialized;
- private boolean loaded;
- private Type pathConfigConstructor = null;
-
- public StaticChecker(OutputStream stderr, OutputStream stdout) {
- GlobalEnvironment heap = new GlobalEnvironment();
- ModuleEnvironment root = heap.addModule(new ModuleEnvironment("$staticchecker$", heap));
- eval = new Evaluator(ValueFactoryFactory.getValueFactory(), System.in, stderr, stdout, root, heap, IRascalMonitor.buildConsoleMonitor(System.in, System.out));
- eval.addRascalSearchPathContributor(StandardLibraryContributor.getInstance());
- checkerEnabled = false;
- initialized = false;
- loaded = false;
- }
-
- private IValue eval(IRascalMonitor monitor, String cmd) {
- try {
- return eval.eval(monitor, cmd, URIUtil.rootLocation("checker")).getValue();
- } catch (ParseError pe) {
- throw new ImplementationError("syntax error in static checker modules", pe);
- }
- }
-
- public synchronized void load(IRascalMonitor monitor) {
- eval(monitor, "import lang::rascal::types::CheckTypes;");
- eval(monitor, "import util::Reflective;");
- TypeStore ts = eval.getHeap().getModule("util::Reflective").getStore();
- pathConfigConstructor = ts.lookupConstructor(ts.lookupAbstractDataType("PathConfig"), "pathConfig").iterator().next();
- loaded = true;
- }
-
- public void init() {
- initialized = true;
- }
-
- public Configuration getConfiguration() {
- return eval.getConfiguration();
- }
-
- public boolean isInitialized() {
- return initialized;
- }
-
- public synchronized ITree checkModule(IRascalMonitor monitor, ISourceLocation module) {
- if (checkerEnabled) {
- return (ITree) eval.call(monitor, "check", module, getPathConfig());
- }
- return null;
- }
-
- private IValue getPathConfig() {
- assert pathConfigConstructor != null;
- IValueFactory vf = ValueFactoryFactory.getValueFactory();
- Map kwArgs = new HashMap<>();
- kwArgs.put("srcPath", vf.list(eval.getRascalResolver().collect().toArray(new IValue[0])));
- // default args for the rest
- return vf.constructor(pathConfigConstructor, new IValue[0], kwArgs);
- }
-
- public synchronized void disableChecker() {
- checkerEnabled = false;
- }
-
- public synchronized void enableChecker(IRascalMonitor monitor) {
- if (!loaded) {
- load(monitor);
- }
- checkerEnabled = true;
- }
-
- public boolean isCheckerEnabled() {
- return checkerEnabled;
- }
-
- public void addRascalSearchPath(ISourceLocation uri) {
- eval.addRascalSearchPath(uri);
- }
-
- public void addClassLoader(ClassLoader classLoader) {
- eval.addClassLoader(classLoader);
- }
-
- public Evaluator getEvaluator() {
- return eval;
- }
-}
diff --git a/src/org/rascalmpl/debug/IRascalMonitor.java b/src/org/rascalmpl/debug/IRascalMonitor.java
index 06452422f98..d64c219a3c8 100644
--- a/src/org/rascalmpl/debug/IRascalMonitor.java
+++ b/src/org/rascalmpl/debug/IRascalMonitor.java
@@ -12,21 +12,18 @@
*******************************************************************************/
package org.rascalmpl.debug;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintStream;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
+
+import org.jline.terminal.Terminal;
import org.rascalmpl.interpreter.BatchProgressMonitor;
import org.rascalmpl.interpreter.NullRascalMonitor;
import org.rascalmpl.repl.TerminalProgressBarMonitor;
import io.usethesource.vallang.ISourceLocation;
-import jline.Terminal;
-import jline.TerminalFactory;
public interface IRascalMonitor {
/**
@@ -158,8 +155,8 @@ default void jobStep(String name, String message) {
* and otherwise default to a dumn terminal console progress logger.
* @return
*/
- public static IRascalMonitor buildConsoleMonitor(InputStream in, OutputStream out) {
- return buildConsoleMonitor(in, out, inBatchMode());
+ public static IRascalMonitor buildConsoleMonitor(Terminal term) {
+ return buildConsoleMonitor(term, inBatchMode());
}
public static boolean inBatchMode() {
@@ -168,12 +165,11 @@ public static boolean inBatchMode() {
;
}
- public static IRascalMonitor buildConsoleMonitor(InputStream in, OutputStream out, boolean batchMode) {
- Terminal terminal = TerminalFactory.get();
+ public static IRascalMonitor buildConsoleMonitor(Terminal terminal, boolean batchMode) {
- return !batchMode && terminal.isAnsiSupported()
- ? new TerminalProgressBarMonitor(out, in, terminal)
- : new BatchProgressMonitor(new PrintStream(out))
+ return !batchMode && TerminalProgressBarMonitor.shouldWorkIn(terminal)
+ ? new TerminalProgressBarMonitor(terminal)
+ : new BatchProgressMonitor(terminal.writer())
;
}
diff --git a/src/org/rascalmpl/ideservices/BasicIDEServices.java b/src/org/rascalmpl/ideservices/BasicIDEServices.java
index f799fdecb4a..2e9ccbaa3e8 100644
--- a/src/org/rascalmpl/ideservices/BasicIDEServices.java
+++ b/src/org/rascalmpl/ideservices/BasicIDEServices.java
@@ -20,6 +20,7 @@
import java.nio.file.Path;
import java.nio.file.Paths;
+import org.jline.terminal.Terminal;
import org.rascalmpl.debug.IRascalMonitor;
import org.rascalmpl.uri.URIResolverRegistry;
import org.rascalmpl.uri.URIUtil;
@@ -34,16 +35,24 @@
public class BasicIDEServices implements IDEServices {
private final IRascalMonitor monitor;
private final PrintWriter stderr;
+ private final Terminal terminal;
- public BasicIDEServices(PrintWriter stderr, IRascalMonitor monitor){
+ public BasicIDEServices(PrintWriter stderr, IRascalMonitor monitor, Terminal terminal){
this.stderr = stderr;
this.monitor = monitor;
+ this.terminal = terminal;
}
@Override
public PrintWriter stderr() {
return stderr;
}
+
+ @Override
+ public Terminal activeTerminal() {
+ return terminal;
+ }
+
public void browse(ISourceLocation loc, String title, int viewColumn){
browse(loc.getURI(), title, viewColumn);
diff --git a/src/org/rascalmpl/ideservices/IDEServices.java b/src/org/rascalmpl/ideservices/IDEServices.java
index c5164d95071..e85d06c4deb 100644
--- a/src/org/rascalmpl/ideservices/IDEServices.java
+++ b/src/org/rascalmpl/ideservices/IDEServices.java
@@ -15,6 +15,7 @@
import java.io.PrintWriter;
import java.net.URI;
+import org.jline.terminal.Terminal;
import org.rascalmpl.debug.IRascalMonitor;
import org.rascalmpl.uri.LogicalMapResolver;
import org.rascalmpl.uri.URIResolverRegistry;
@@ -73,6 +74,16 @@ default void unregisterLanguage(IConstructor language) {
throw new UnsupportedOperationException("registerLanguage is not implemented in this environment.");
}
+ /**
+ * Get access to the current terminal.
+ * used for features such as clearing the terminal, and starting a nested REPL.
+ * Can return null if there is no active terminal.
+ * @return a terminal if there is one, null otherwise.
+ */
+ default Terminal activeTerminal() {
+ return null;
+ }
+
/**
* Asks the IDE to apply document edits as defined in the standard library module
* analysis::diff::edits::TextEdits, according to the semantics defined in
diff --git a/src/org/rascalmpl/interpreter/BatchProgressMonitor.java b/src/org/rascalmpl/interpreter/BatchProgressMonitor.java
index 82793b67d80..3da79f59810 100644
--- a/src/org/rascalmpl/interpreter/BatchProgressMonitor.java
+++ b/src/org/rascalmpl/interpreter/BatchProgressMonitor.java
@@ -24,11 +24,15 @@ public class BatchProgressMonitor implements IRascalMonitor {
PrintWriter out;
public BatchProgressMonitor() {
- this.out = new PrintWriter(System.err);
+ this(new PrintWriter(System.err, true));
}
public BatchProgressMonitor(PrintStream out) {
- this.out = new PrintWriter(out);
+ this(new PrintWriter(out, true));
+ }
+
+ public BatchProgressMonitor(PrintWriter out) {
+ this.out = out;
}
@Override
diff --git a/src/org/rascalmpl/interpreter/DefaultTestResultListener.java b/src/org/rascalmpl/interpreter/DefaultTestResultListener.java
index 9d4ced0c270..a15d5529627 100644
--- a/src/org/rascalmpl/interpreter/DefaultTestResultListener.java
+++ b/src/org/rascalmpl/interpreter/DefaultTestResultListener.java
@@ -15,7 +15,7 @@
import java.io.PrintWriter;
-import org.rascalmpl.repl.ReplTextWriter;
+import org.rascalmpl.repl.streams.ReplTextWriter;
import io.usethesource.vallang.ISourceLocation;
@@ -28,14 +28,16 @@ public class DefaultTestResultListener implements ITestResultListener {
private String context;
private final boolean verbose;
private PrintWriter out;
+ private PrintWriter err;
- public DefaultTestResultListener(PrintWriter out) {
- this(out, true);
+ public DefaultTestResultListener(PrintWriter out, PrintWriter err) {
+ this(out, err, true);
}
- public DefaultTestResultListener(PrintWriter out, boolean verbose){
+ public DefaultTestResultListener(PrintWriter out, PrintWriter err, boolean verbose){
super();
+ this.err = err;
this.out = out;
this.verbose = verbose;
reset();
@@ -49,7 +51,7 @@ private void reset() {
}
public void setErrorStream(PrintWriter errorStream) {
- this.out = errorStream;
+ this.err = errorStream;
}
@Override
@@ -71,14 +73,14 @@ public void done() {
// make sure results are reported on a newline
out.println();
}
- out.println("\rTest report for " + context);
+ out.println("Test report for " + context);
if (errors + failures == 0) {
out.println("\tall " + (count - ignored) + "/" + count + " tests succeeded");
}
else {
out.println("\t" + successes + "/" + count + " tests succeeded");
- out.println("\t" + failures + "/" + count + " tests failed");
- out.println("\t" + errors + "/" + count + " tests threw exceptions");
+ err.println("\t" + failures + "/" + count + " tests failed");
+ err.println("\t" + errors + "/" + count + " tests threw exceptions");
}
if (ignored != 0) {
@@ -86,6 +88,7 @@ public void done() {
}
out.flush();
+ err.flush();
}
}
@@ -99,9 +102,10 @@ else if (t != null) {
errors++;
if (!verbose) {
out.println();
+ out.flush();
}
- out.println("error: " + test + " @ " + ReplTextWriter.valueToString(loc));
- out.println(message);
+ err.println("error: " + test + " @ " + ReplTextWriter.valueToString(loc));
+ err.println(message);
}
else {
failures++;
diff --git a/src/org/rascalmpl/interpreter/Evaluator.java b/src/org/rascalmpl/interpreter/Evaluator.java
index 5183ce362df..0f271f7bea0 100755
--- a/src/org/rascalmpl/interpreter/Evaluator.java
+++ b/src/org/rascalmpl/interpreter/Evaluator.java
@@ -22,16 +22,11 @@
import static org.rascalmpl.semantics.dynamic.Import.parseFragments;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringReader;
import java.net.URI;
-import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
-import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
@@ -41,9 +36,10 @@
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
+import java.util.SortedMap;
import java.util.SortedSet;
import java.util.Stack;
-import java.util.TreeSet;
+import java.util.TreeMap;
import java.util.concurrent.CopyOnWriteArrayList;
import org.rascalmpl.ast.AbstractAST;
@@ -99,7 +95,6 @@
import org.rascalmpl.parser.gtd.result.out.DefaultNodeFlattener;
import org.rascalmpl.parser.uptr.UPTRNodeFactory;
import org.rascalmpl.parser.uptr.action.NoActionExecutor;
-import org.rascalmpl.repl.TerminalProgressBarMonitor;
import org.rascalmpl.uri.URIResolverRegistry;
import org.rascalmpl.uri.URIUtil;
import org.rascalmpl.values.RascalFunctionValueFactory;
@@ -195,17 +190,13 @@ public void decCallNesting() {
private final List classLoaders; // sharable if frozen
private final ModuleEnvironment rootScope; // sharable if frozen
- private final OutputStream defStderr;
- private final OutputStream defStdout;
private final PrintWriter defOutWriter;
private final PrintWriter defErrWriter;
- private final InputStream defInput;
+ private final Reader defInput;
- private OutputStream curStderr = null;
- private OutputStream curStdout = null;
private PrintWriter curOutWriter = null;
private PrintWriter curErrWriter = null;
- private InputStream curInput = null;
+ private Reader curInput = null;
/**
* Probably not sharable
@@ -232,26 +223,26 @@ public void decCallNesting() {
private static final Object dummy = new Object();
/**
- * Promotes the monitor to the outputstream automatically if so required.
+ * Promotes the monitor to the PrintWriter automatically if so required.
*/
- public Evaluator(IValueFactory f, InputStream input, OutputStream stderr, OutputStream stdout, IRascalMonitor monitor, ModuleEnvironment scope, GlobalEnvironment heap) {
- this(f, input, stderr, monitor instanceof OutputStream ? (OutputStream) monitor : stdout, scope, heap, new ArrayList(Collections.singleton(Evaluator.class.getClassLoader())), new RascalSearchPath());
+ public Evaluator(IValueFactory f, Reader input, PrintWriter stderr, PrintWriter stdout, IRascalMonitor monitor, ModuleEnvironment scope, GlobalEnvironment heap) {
+ this(f, input, stderr, monitor instanceof PrintWriter ? (PrintWriter) monitor : stdout, scope, heap, new ArrayList(Collections.singleton(Evaluator.class.getClassLoader())), new RascalSearchPath());
}
/**
* If your monitor should wrap stdout (like TerminalProgressBarMonitor) then you can use this constructor.
*/
- public Evaluator(IValueFactory f, InputStream input, OutputStream stderr, M monitor, ModuleEnvironment scope, GlobalEnvironment heap) {
+ public Evaluator(IValueFactory f, Reader input, PrintWriter stderr, M monitor, ModuleEnvironment scope, GlobalEnvironment heap) {
this(f, input, stderr, monitor, scope, heap, new ArrayList(Collections.singleton(Evaluator.class.getClassLoader())), new RascalSearchPath());
setMonitor(monitor);
}
- public Evaluator(IValueFactory f, InputStream input, OutputStream stderr, OutputStream stdout, ModuleEnvironment scope, GlobalEnvironment heap, IRascalMonitor monitor) {
- this(f, input, stderr, monitor instanceof OutputStream ? (OutputStream) monitor : stdout, scope, heap, new ArrayList(Collections.singleton(Evaluator.class.getClassLoader())), new RascalSearchPath());
+ public Evaluator(IValueFactory f, Reader input, PrintWriter stderr, PrintWriter stdout, ModuleEnvironment scope, GlobalEnvironment heap, IRascalMonitor monitor) {
+ this(f, input, stderr, monitor instanceof PrintWriter ? (PrintWriter) monitor : stdout, scope, heap, new ArrayList(Collections.singleton(Evaluator.class.getClassLoader())), new RascalSearchPath());
setMonitor(monitor);
}
- public Evaluator(IValueFactory vf, InputStream input, OutputStream stderr, OutputStream stdout, ModuleEnvironment scope, GlobalEnvironment heap, List classLoaders, RascalSearchPath rascalPathResolver) {
+ public Evaluator(IValueFactory vf, Reader input, PrintWriter stderr, PrintWriter stdout, ModuleEnvironment scope, GlobalEnvironment heap, List classLoaders, RascalSearchPath rascalPathResolver) {
super();
this.vf = new RascalFunctionValueFactory(this);
@@ -265,10 +256,8 @@ public Evaluator(IValueFactory vf, InputStream input, OutputStream stderr, Outpu
this.rascalPathResolver = rascalPathResolver;
this.resolverRegistry = rascalPathResolver.getRegistry();
this.defInput = input;
- this.defStderr = stderr;
- this.defStdout = stdout;
- this.defErrWriter = wrapWriter(stderr, true);
- this.defOutWriter = wrapWriter(stdout, false);
+ this.defErrWriter = stderr;
+ this.defOutWriter = stdout;
this.constructorDeclaredListeners = new HashMap();
this.suspendTriggerListeners = new CopyOnWriteArrayList();
@@ -285,10 +274,6 @@ public Evaluator(IValueFactory vf, InputStream input, OutputStream stderr, Outpu
setEventTrigger(AbstractInterpreterEventTrigger.newNullEventTrigger());
}
- private static PrintWriter wrapWriter(OutputStream out, boolean autoFlush) {
- return new PrintWriter(new OutputStreamWriter(out, StandardCharsets.UTF_8), autoFlush);
- }
-
private Evaluator(Evaluator source, ModuleEnvironment scope) {
super();
@@ -307,8 +292,6 @@ private Evaluator(Evaluator source, ModuleEnvironment scope) {
this.javaBridge = new JavaBridge(classLoaders, vf, config);
this.rascalPathResolver = source.rascalPathResolver;
this.resolverRegistry = source.resolverRegistry;
- this.defStderr = source.defStderr;
- this.defStdout = source.defStdout;
this.defInput = source.defInput;
this.defErrWriter = source.defErrWriter;
this.defOutWriter = source.defOutWriter;
@@ -398,29 +381,20 @@ public List getClassLoaders() {
return Collections.unmodifiableList(classLoaders);
}
- @Override
+ @Override
public ModuleEnvironment __getRootScope() {
return rootScope;
}
- @Override
- public OutputStream getStdOut() {
- return curStdout == null ? defStdout : curStdout;
- }
-
@Override
public PrintWriter getOutPrinter() {
- return curOutWriter == null ? defOutWriter : curOutWriter;
- }
-
- @Override
- public PrintWriter getErrorPrinter() {
- return curErrWriter == null ? defErrWriter : curErrWriter;
+ return curOutWriter == null ? defOutWriter : curOutWriter;
}
+
@Override
- public InputStream getInput() {
+ public Reader getInput() {
return curInput == null ? defInput : curInput;
}
@@ -469,9 +443,9 @@ public boolean isInterrupted() {
return interrupt;
}
- @Override
- public OutputStream getStdErr() {
- return curStderr == null ? defStderr : curStderr;
+ @Override
+ public PrintWriter getErrorPrinter() {
+ return curErrWriter == null ? defErrWriter : curErrWriter;
}
public void setTestResultListener(ITestResultListener l) {
@@ -831,7 +805,8 @@ public ParserGenerator getParserGenerator() {
synchronized (self) {
if (parserGenerator == null) {
- parserGenerator = new ParserGenerator(getMonitor(), (monitor instanceof TerminalProgressBarMonitor) ? (OutputStream) getMonitor() : getStdErr(), classLoaders, getValueFactory(), config);
+
+ parserGenerator = new ParserGenerator(getMonitor(), (monitor instanceof PrintWriter) ? (PrintWriter)monitor : getErrorPrinter(), classLoaders, getValueFactory(), config);
}
}
}
@@ -1513,7 +1488,7 @@ public boolean runTests(IRascalMonitor monitor) {
IRascalMonitor old = setMonitor(monitor);
try {
final boolean[] allOk = new boolean[] { true };
- final ITestResultListener l = testReporter != null ? testReporter : new DefaultTestResultListener(getOutPrinter());
+ final ITestResultListener l = testReporter != null ? testReporter : new DefaultTestResultListener(getOutPrinter(), getErrorPrinter());
new TestEvaluator(this, new ITestResultListener() {
@@ -1578,17 +1553,13 @@ public IRascalMonitor getMonitor() {
return new NullRascalMonitor();
}
- public void overrideDefaultWriters(InputStream newInput, OutputStream newStdOut, OutputStream newStdErr) {
- this.curStdout = newStdOut;
- this.curStderr = newStdErr;
+ public void overrideDefaultWriters(Reader newInput, PrintWriter newStdOut, PrintWriter newStdErr) {
this.curInput = newInput;
- this.curErrWriter = wrapWriter(newStdErr, true);
- this.curOutWriter = wrapWriter(newStdOut, false);
+ this.curErrWriter = newStdErr;
+ this.curOutWriter = newStdOut;
}
public void revertToDefaultWriters() {
- this.curStderr = null;
- this.curStdout = null;
this.curInput = null;
if (curOutWriter != null) {
curOutWriter.flush();
@@ -1707,13 +1678,13 @@ public TraversalEvaluator __popTraversalEvaluator() {
}
@Override
- public Collection completePartialIdentifier(String qualifier, String partialIdentifier) {
+ public Map completePartialIdentifier(String qualifier, String partialIdentifier) {
if (partialIdentifier.startsWith("\\")) {
partialIdentifier = partialIdentifier.substring(1);
}
String partialModuleName = qualifier + "::" + partialIdentifier;
- SortedSet result = new TreeSet<>(new Comparator() {
+ SortedMap result = new TreeMap<>(new Comparator() {
@Override
public int compare(String a, String b) {
if (a.charAt(0) == '\\') {
@@ -1735,7 +1706,7 @@ public int compare(String a, String b) {
return result;
}
- private void addCompletionsForModule(String qualifier, String partialIdentifier, String partialModuleName, SortedSet result, ModuleEnvironment env, boolean skipPrivate) {
+ private void addCompletionsForModule(String qualifier, String partialIdentifier, String partialModuleName, SortedMap result, ModuleEnvironment env, boolean skipPrivate) {
for (Pair> p : env.getFunctions()) {
for (AbstractFunction f : p.getSecond()) {
String module = ((ModuleEnvironment)f.getEnv()).getName();
@@ -1745,7 +1716,7 @@ private void addCompletionsForModule(String qualifier, String partialIdentifier,
}
if (module.startsWith(qualifier)) {
- addIt(result, p.getFirst(), qualifier.isEmpty() ? "" : module, module.startsWith(partialModuleName) ? "" : partialIdentifier);
+ addCandidate(result, "function", p.getFirst(), qualifier.isEmpty() ? "" : module, module.startsWith(partialModuleName) ? "" : partialIdentifier);
}
}
}
@@ -1755,38 +1726,38 @@ private void addCompletionsForModule(String qualifier, String partialIdentifier,
if (skipPrivate && env.isNamePrivate(entry.getKey())) {
continue;
}
- addIt(result, entry.getKey(), qualifier, partialIdentifier);
+ addCandidate(result, "variable", entry.getKey(), qualifier, partialIdentifier);
}
for (Type t: env.getAbstractDatatypes()) {
if (inQualifiedModule) {
- addIt(result, t.getName(), qualifier, partialIdentifier);
+ addCandidate(result, "ADT", t.getName(), qualifier, partialIdentifier);
}
}
for (Type t: env.getAliases()) {
- addIt(result, t.getName(), qualifier, partialIdentifier);
+ addCandidate(result, "alias", t.getName(), qualifier, partialIdentifier);
}
}
if (qualifier.isEmpty()) {
Map> annos = env.getAnnotations();
for (Type t: annos.keySet()) {
for (String k: annos.get(t).keySet()) {
- addIt(result, k, "", partialIdentifier);
+ addCandidate(result, "annotation", k, "", partialIdentifier);
}
}
}
}
- private static void addIt(SortedSet result, String v, String qualifier, String originalTerm) {
- if (v.startsWith(originalTerm) && !v.equals(originalTerm)) {
- if (v.contains("-")) {
- v = "\\" + v;
+ private static void addCandidate(SortedMap result, String category, String name, String qualifier, String originalTerm) {
+ if (name.startsWith(originalTerm) && !name.equals(originalTerm)) {
+ if (name.contains("-")) {
+ name = "\\" + name;
}
- if (!qualifier.isEmpty() && !v.startsWith(qualifier)) {
- v = qualifier + "::" + v;
+ if (!qualifier.isEmpty() && !name.startsWith(qualifier)) {
+ name = qualifier + "::" + name;
}
- result.add(v);
+ result.put(name, category);
}
}
@@ -1983,4 +1954,10 @@ public void showMessage(IConstructor message) {
}
}
}
+
+
+ public void overwritePrintWriter(PrintWriter outWriter, PrintWriter errWriter) {
+ this.curOutWriter = outWriter;
+ this.curErrWriter = errWriter;
+ }
}
diff --git a/src/org/rascalmpl/interpreter/IEvaluatorContext.java b/src/org/rascalmpl/interpreter/IEvaluatorContext.java
index 49db817c31b..4cb527af3f3 100644
--- a/src/org/rascalmpl/interpreter/IEvaluatorContext.java
+++ b/src/org/rascalmpl/interpreter/IEvaluatorContext.java
@@ -17,10 +17,10 @@
*******************************************************************************/
package org.rascalmpl.interpreter;
-import java.io.InputStream;
-import java.io.OutputStream;
import java.io.PrintWriter;
+import java.io.Reader;
import java.util.Collection;
+import java.util.Map;
import java.util.Stack;
import org.rascalmpl.ast.AbstractAST;
@@ -43,11 +43,8 @@ public interface IEvaluatorContext extends IRascalMonitor {
/** for standard IO */
public PrintWriter getOutPrinter();
public PrintWriter getErrorPrinter();
-
- public OutputStream getStdOut();
- public OutputStream getStdErr();
- public InputStream getInput();
+ public Reader getInput();
/** for "internal use" */
public IEvaluator> getEvaluator();
@@ -77,5 +74,7 @@ public interface IEvaluatorContext extends IRascalMonitor {
public Stack getAccumulators();
- public Collection completePartialIdentifier(String qualifier, String partialIdentifier);
+ /** Given a (possibly empty) qualifier and a partial identifier, look in the current root environment if there are names defined that could match the partial names
+ * @return identifiers and their category (variable, function, etc) */
+ public Map completePartialIdentifier(String qualifier, String partialIdentifier);
}
diff --git a/src/org/rascalmpl/interpreter/result/JavaMethod.java b/src/org/rascalmpl/interpreter/result/JavaMethod.java
index 10530bda752..d10e1833f30 100644
--- a/src/org/rascalmpl/interpreter/result/JavaMethod.java
+++ b/src/org/rascalmpl/interpreter/result/JavaMethod.java
@@ -91,7 +91,7 @@ private JavaMethod(IEvaluator> eval, Type staticType, Type dynami
super(func, eval, staticType, dynamicType, getFormals(func), Names.name(func.getSignature().getName()), isDefault, isTest, varargs, env);
this.javaBridge = javaBridge;
this.hasReflectiveAccess = hasReflectiveAccess(func);
- this.instance = javaBridge.getJavaClassInstance(func, eval.getMonitor(), env.getStore(), eval.getOutPrinter(), eval.getErrorPrinter(), eval.getStdOut(), eval.getStdErr(), eval.getInput(), eval);
+ this.instance = javaBridge.getJavaClassInstance(func, eval.getMonitor(), env.getStore(), eval.getOutPrinter(), eval.getErrorPrinter(), eval.getInput(), eval);
this.method = javaBridge.lookupJavaMethod(eval, func, env, hasReflectiveAccess);
}
diff --git a/src/org/rascalmpl/interpreter/utils/JavaBridge.java b/src/org/rascalmpl/interpreter/utils/JavaBridge.java
index 71362ef5f39..ef045e4538b 100644
--- a/src/org/rascalmpl/interpreter/utils/JavaBridge.java
+++ b/src/org/rascalmpl/interpreter/utils/JavaBridge.java
@@ -19,6 +19,7 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
+import java.io.Reader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -376,14 +377,11 @@ public Class> visitFunction(Type type) throws RuntimeException {
}
}
- public synchronized Object getJavaClassInstance(FunctionDeclaration func, IRascalMonitor monitor, TypeStore store, PrintWriter out, PrintWriter err, OutputStream rawOut, OutputStream rawErr, InputStream in, IEvaluatorContext ctx) {
+ public synchronized Object getJavaClassInstance(FunctionDeclaration func, IRascalMonitor monitor, TypeStore store, PrintWriter out, PrintWriter err, Reader in, IEvaluatorContext ctx) {
String className = getClassName(func);
PrintWriter[] outputs = new PrintWriter[] { out, err };
int writers = 0;
-
- OutputStream[] rawOutputs = new OutputStream[] { rawOut, rawErr };
- int rawWriters = 0;
try {
for(ClassLoader loader : loaders){
@@ -426,10 +424,7 @@ else if (formals[i].isAssignableFrom(TypeFactory.class)) {
else if (formals[i].isAssignableFrom(PrintWriter.class)) {
args[i] = outputs[writers++ % 2];
}
- else if (formals[i].isAssignableFrom(OutputStream.class)) {
- args[i] = rawOutputs[rawWriters++ %2];
- }
- else if (formals[i].isAssignableFrom(InputStream.class)) {
+ else if (formals[i].isAssignableFrom(Reader.class)) {
args[i] = in;
}
else if (formals[i].isAssignableFrom(IRascalMonitor.class)) {
@@ -446,7 +441,7 @@ else if (formals[i].isAssignableFrom(IDEServices.class)) {
args[i] = (IDEServices) monitor;
}
else {
- args[i] = new BasicIDEServices(err, monitor);
+ args[i] = new BasicIDEServices(err, monitor, null);
}
}
else if (formals[i].isAssignableFrom(IResourceLocationProvider.class)) {
diff --git a/src/org/rascalmpl/library/Prelude.java b/src/org/rascalmpl/library/Prelude.java
index 75f95c58cd6..2224a6c39ac 100644
--- a/src/org/rascalmpl/library/Prelude.java
+++ b/src/org/rascalmpl/library/Prelude.java
@@ -78,7 +78,7 @@
import org.rascalmpl.exceptions.Throw;
import org.rascalmpl.ideservices.IDEServices;
import org.rascalmpl.interpreter.utils.IResourceLocationProvider;
-import org.rascalmpl.repl.LimitedLineWriter;
+import org.rascalmpl.repl.streams.LimitedLineWriter;
import org.rascalmpl.types.TypeReifier;
import org.rascalmpl.unicode.UnicodeOffsetLengthReader;
import org.rascalmpl.unicode.UnicodeOutputStreamWriter;
diff --git a/src/org/rascalmpl/library/lang/json/internal/JsonValueWriter.java b/src/org/rascalmpl/library/lang/json/internal/JsonValueWriter.java
index 92e7e230b17..02c91578e0d 100644
--- a/src/org/rascalmpl/library/lang/json/internal/JsonValueWriter.java
+++ b/src/org/rascalmpl/library/lang/json/internal/JsonValueWriter.java
@@ -26,6 +26,7 @@
import java.util.Map;
import java.util.Map.Entry;
+import org.checkerframework.checker.nullness.qual.Nullable;
import org.rascalmpl.exceptions.RuntimeExceptionFactory;
import org.rascalmpl.exceptions.Throw;
import org.rascalmpl.library.Prelude;
@@ -52,7 +53,6 @@
import io.usethesource.vallang.ITuple;
import io.usethesource.vallang.IValue;
import io.usethesource.vallang.visitors.IValueVisitor;
-import jline.internal.Nullable;
/**
* This class streams an IValue directly to an JSON stream. Useful to communicate IValues to
diff --git a/src/org/rascalmpl/library/util/Eval.java b/src/org/rascalmpl/library/util/Eval.java
index 6da394f8621..dd2835f8f46 100644
--- a/src/org/rascalmpl/library/util/Eval.java
+++ b/src/org/rascalmpl/library/util/Eval.java
@@ -16,8 +16,8 @@
import java.io.File;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.Reader;
import java.net.URISyntaxException;
import java.nio.file.Paths;
import java.util.HashMap;
@@ -80,12 +80,12 @@ public class Eval {
private final Type execConstructor;
/* the following four fields are inherited by the configuration of nested evaluators */
- private final OutputStream stderr;
- private final OutputStream stdout;
- private final InputStream input;
+ private final PrintWriter stderr;
+ private final PrintWriter stdout;
+ private final Reader input;
private final IDEServices services;
- public Eval(IRascalValueFactory values, OutputStream out, OutputStream err, InputStream in, ClassLoader loader, IDEServices services, TypeStore ts) {
+ public Eval(IRascalValueFactory values, PrintWriter out, PrintWriter err, Reader in, ClassLoader loader, IDEServices services, TypeStore ts) {
super();
this.values = values;
this.tr = new TypeReifier(values);
@@ -219,7 +219,7 @@ private static class RascalRuntime {
private final Evaluator eval;
private int duration = -1;
- public RascalRuntime(PathConfig pcfg, InputStream input, OutputStream stderr, OutputStream stdout, IDEServices services) throws IOException, URISyntaxException{
+ public RascalRuntime(PathConfig pcfg, Reader input, PrintWriter stderr, PrintWriter stdout, IDEServices services) throws IOException, URISyntaxException{
GlobalEnvironment heap = new GlobalEnvironment();
ModuleEnvironment root = heap.addModule(new ModuleEnvironment(ModuleEnvironment.SHELL_MODULE, heap));
IValueFactory vf = ValueFactoryFactory.getValueFactory();
diff --git a/src/org/rascalmpl/library/util/IDEServicesLibrary.java b/src/org/rascalmpl/library/util/IDEServicesLibrary.java
index 5476c5d2509..3798e7d0e0a 100644
--- a/src/org/rascalmpl/library/util/IDEServicesLibrary.java
+++ b/src/org/rascalmpl/library/util/IDEServicesLibrary.java
@@ -16,8 +16,8 @@
import org.rascalmpl.exceptions.RuntimeExceptionFactory;
import org.rascalmpl.ideservices.IDEServices;
-import org.rascalmpl.repl.REPLContentServer;
-import org.rascalmpl.repl.REPLContentServerManager;
+import org.rascalmpl.repl.http.REPLContentServer;
+import org.rascalmpl.repl.http.REPLContentServerManager;
import org.rascalmpl.uri.URIUtil;
import org.rascalmpl.values.IRascalValueFactory;
import org.rascalmpl.values.functions.IFunction;
diff --git a/src/org/rascalmpl/library/util/REPL.rsc b/src/org/rascalmpl/library/util/REPL.rsc
index 54eaa45bf9b..b429c376c1f 100644
--- a/src/org/rascalmpl/library/util/REPL.rsc
+++ b/src/org/rascalmpl/library/util/REPL.rsc
@@ -2,8 +2,7 @@ module util::REPL
extend Content;
-alias Completion
- = tuple[int offset, list[str] suggestions];
+alias Completion = map[str completion, str group];
data REPL
= repl(
@@ -13,13 +12,13 @@ data REPL
str quit = "",
loc history = |home:///.term-repl-history|,
Content (str command) handler = echo,
- Completion(str line, int cursor) completor = noSuggestions,
+ Completion(str line, str word) completor = noSuggestions,
str () stacktrace = str () { return ""; }
);
private Content echo(str line) = plainText(line);
-private Completion noSuggestions(str _, int _) = <0, []>;
+private Completion noSuggestions(str _, str _) = ();
alias Terminal = tuple[void() run, void(str) send];
@@ -36,7 +35,7 @@ java Terminal newREPL(REPL repl,
str quit = repl.quit,
loc history = repl.history,
Content (str ) handler = repl.handler,
- Completion(str , int) completor = repl.completor,
+ Completion(str , str) completor = repl.completor,
str () stacktrace = repl.stacktrace);
void startREPL(REPL repl,
@@ -48,7 +47,7 @@ void startREPL(REPL repl,
str quit = repl.quit,
loc history = repl.history,
Content (str ) handler = repl.handler,
- Completion(str , int) completor = repl.completor,
+ Completion(str , str) completor = repl.completor,
str () stacktrace = repl.stacktrace) {
Terminal tm = newREPL(repl, title=title, welcome=welcome,
diff --git a/src/org/rascalmpl/library/util/Reflective.java b/src/org/rascalmpl/library/util/Reflective.java
index 44bb23ce3b1..dba61d268b8 100644
--- a/src/org/rascalmpl/library/util/Reflective.java
+++ b/src/org/rascalmpl/library/util/Reflective.java
@@ -43,8 +43,8 @@
import org.rascalmpl.parser.gtd.result.out.DefaultNodeFlattener;
import org.rascalmpl.parser.uptr.UPTRNodeFactory;
import org.rascalmpl.parser.uptr.action.NoActionExecutor;
-import org.rascalmpl.repl.LimitedLineWriter;
-import org.rascalmpl.repl.LimitedWriter;
+import org.rascalmpl.repl.streams.LimitedLineWriter;
+import org.rascalmpl.repl.streams.LimitedWriter;
import org.rascalmpl.uri.URIResolverRegistry;
import org.rascalmpl.values.RascalValueFactory;
import org.rascalmpl.values.ValueFactoryFactory;
@@ -99,21 +99,23 @@ public IConstructor getProjectPathConfig(ISourceLocation projectRoot, IConstruct
}
}
- IEvaluator> getDefaultEvaluator(OutputStream stdout, OutputStream stderr) {
+ IEvaluator> getDefaultEvaluator(PrintWriter stdout, PrintWriter stderr) {
GlobalEnvironment heap = new GlobalEnvironment();
ModuleEnvironment root = heap.addModule(new ModuleEnvironment(ModuleEnvironment.SHELL_MODULE, heap));
IValueFactory vf = ValueFactoryFactory.getValueFactory();
- Evaluator evaluator = new Evaluator(vf, System.in, stderr, stdout, root, heap, monitor);
+ Evaluator evaluator = new Evaluator(vf, Reader.nullReader(), stderr, stdout, root, heap, monitor);
evaluator.addRascalSearchPathContributor(StandardLibraryContributor.getInstance());
return evaluator;
}
public IList evalCommands(IList commands, ISourceLocation loc) {
- OutputStream out = new ByteArrayOutputStream();
- OutputStream err = new ByteArrayOutputStream();
+ StringWriter out = new StringWriter();
+ StringWriter err = new StringWriter();
+ PrintWriter outStream = new PrintWriter(out);
+ PrintWriter errStream = new PrintWriter(err);
IListWriter result = values.listWriter();
- IEvaluator> evaluator = getDefaultEvaluator(out, err);
+ IEvaluator> evaluator = getDefaultEvaluator(outStream, errStream);
int outOffset = 0;
int errOffset = 0;
@@ -125,11 +127,16 @@ public IList evalCommands(IList commands, ISourceLocation loc) {
x = evaluator.eval(evaluator.getMonitor(), ((IString)v).getValue(), loc);
}
catch (Throwable e) {
+ errStream.flush();
errOut = err.toString().substring(errOffset);
errOffset += errOut.length();
errOut += e.getMessage();
exc = true;
}
+ finally {
+ outStream.flush();
+ errStream.flush();
+ }
String output = out.toString().substring(outOffset);
outOffset += output.length();
if (!exc) {
diff --git a/src/org/rascalmpl/library/util/TermREPL.java b/src/org/rascalmpl/library/util/TermREPL.java
index 335d1ed1a3e..35baa3e45e4 100644
--- a/src/org/rascalmpl/library/util/TermREPL.java
+++ b/src/org/rascalmpl/library/util/TermREPL.java
@@ -1,18 +1,16 @@
package org.rascalmpl.library.util;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+import java.io.Reader;
import java.io.UnsupportedEncodingException;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.List;
+import java.net.URI;
+import java.nio.file.Path;
+import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
+import org.jline.reader.EndOfFileException;
import org.rascalmpl.exceptions.RuntimeExceptionFactory;
import org.rascalmpl.ideservices.IDEServices;
import org.rascalmpl.interpreter.Evaluator;
@@ -20,11 +18,20 @@
import org.rascalmpl.interpreter.result.AbstractFunction;
import org.rascalmpl.library.lang.json.internal.JsonValueWriter;
import org.rascalmpl.repl.BaseREPL;
-import org.rascalmpl.repl.CompletionResult;
-import org.rascalmpl.repl.ILanguageProtocol;
-import org.rascalmpl.repl.REPLContentServer;
-import org.rascalmpl.repl.REPLContentServerManager;
+import org.rascalmpl.repl.http.REPLContentServer;
+import org.rascalmpl.repl.http.REPLContentServerManager;
+import org.rascalmpl.repl.output.ICommandOutput;
+import org.rascalmpl.repl.output.IErrorCommandOutput;
+import org.rascalmpl.repl.output.INotebookOutput;
+import org.rascalmpl.repl.output.IOutputPrinter;
+import org.rascalmpl.repl.output.ISourceLocationCommandOutput;
+import org.rascalmpl.repl.output.IWebContentOutput;
+import org.rascalmpl.repl.output.MimeTypes;
+import org.rascalmpl.repl.output.impl.AsciiStringOutputPrinter;
+import org.rascalmpl.repl.parametric.ILanguageProtocol;
+import org.rascalmpl.repl.parametric.ParametricReplService;
import org.rascalmpl.uri.URIResolverRegistry;
+import org.rascalmpl.uri.URIUtil;
import org.rascalmpl.values.IRascalValueFactory;
import org.rascalmpl.values.functions.IFunction;
@@ -32,8 +39,7 @@
import io.usethesource.vallang.IBool;
import io.usethesource.vallang.IConstructor;
-import io.usethesource.vallang.IInteger;
-import io.usethesource.vallang.IList;
+import io.usethesource.vallang.IMap;
import io.usethesource.vallang.ISourceLocation;
import io.usethesource.vallang.IString;
import io.usethesource.vallang.ITuple;
@@ -42,29 +48,45 @@
import io.usethesource.vallang.IWithKeywordParameters;
import io.usethesource.vallang.type.Type;
import io.usethesource.vallang.type.TypeFactory;
-import jline.TerminalFactory;
public class TermREPL {
private final IRascalValueFactory vf;
+ private final IDEServices service;
+ private final PrintWriter err;
private ILanguageProtocol lang;
- private final OutputStream out;
- private final OutputStream err;
- private final InputStream in;
- public TermREPL(IRascalValueFactory vf, OutputStream out, OutputStream err, InputStream in) {
+ public TermREPL(IRascalValueFactory vf, IDEServices service, PrintWriter _ignoredOut, PrintWriter err) {
this.vf = vf;
- this.out = out;
+ this.service = service;
this.err = err;
- this.in = in;
+ }
+
+ private Path resolveHistoryFile(ISourceLocation historyFile) {
+ try {
+ ISourceLocation result = URIResolverRegistry.getInstance().logicalToPhysical(historyFile);
+ if (result == null || !result.getScheme().equals("file")) {
+ err.println("Cannot resolve history file to file on disk");
+ return null;
+ }
+ return Path.of(result.getPath());
+ }
+ catch (IOException e) {
+ return null;
+ }
}
public ITuple newREPL(IConstructor repl, IString title, IString welcome, IString prompt, IString quit,
ISourceLocation history, IFunction handler, IFunction completor, IFunction stacktrace, IEvaluatorContext eval) {
- lang = new TheREPL(vf, title, welcome, prompt, quit, history, handler, completor, stacktrace, in, err, out);
+ var term = service.activeTerminal();
+ if (term == null) {
+ throw RuntimeExceptionFactory.io("No terminal found in IDE service, we cannot allocate a REPL");
+ }
+ lang = new TheREPL(vf, title, welcome, prompt, quit, history, handler, completor, stacktrace);
+
BaseREPL baseRepl;
try {
- baseRepl = new BaseREPL(lang, null, in, err, out, true, true, history, TerminalFactory.get(), null);
+ baseRepl = new BaseREPL(new ParametricReplService(lang, service, resolveHistoryFile(history)), term);
}
catch (Throwable e) {
throw RuntimeExceptionFactory.io(e.getMessage());
@@ -94,10 +116,10 @@ public ITuple newREPL(IConstructor repl, IString title, IString welcome, IString
public static class TheREPL implements ILanguageProtocol {
private final REPLContentServerManager contentManager = new REPLContentServerManager();
private final TypeFactory tf = TypeFactory.getInstance();
- private OutputStream stdout;
- private OutputStream stderr;
- private InputStream input;
- private String currentPrompt;
+ private PrintWriter stdout;
+ private PrintWriter stderr;
+ private Reader input;
+ private final String currentPrompt;
private String quit;
private final AbstractFunction handler;
private final AbstractFunction completor;
@@ -105,12 +127,8 @@ public static class TheREPL implements ILanguageProtocol {
private final AbstractFunction stacktrace;
public TheREPL(IValueFactory vf, IString title, IString welcome, IString prompt, IString quit, ISourceLocation history,
- IFunction handler, IFunction completor, IValue stacktrace, InputStream input, OutputStream stderr, OutputStream stdout) {
+ IFunction handler, IFunction completor, IValue stacktrace) {
this.vf = vf;
- this.input = input;
- this.stderr = stderr;
- this.stdout = stdout;
-
// TODO: these casts mean that TheRepl only works with functions produced by the
// interpreter for now. The reason is that the REPL needs access to environment configuration
// parameters of these functions such as stdout, stdin, etc.
@@ -124,100 +142,137 @@ public TheREPL(IValueFactory vf, IString title, IString welcome, IString prompt,
}
@Override
- public void cancelRunningCommandRequested() {
- handler.getEval().interrupt();
- handler.getEval().__setInterrupt(false);
- }
-
- @Override
- public void terminateRequested() {
- handler.getEval().interrupt();
+ public void initialize(Reader input, PrintWriter stdout, PrintWriter stderr, IDEServices services) {
+ this.input = input;
+ this.stdout = stdout;
+ this.stderr = stdout;
}
@Override
- public void stop() {
+ public void cancelRunningCommandRequested() {
handler.getEval().interrupt();
}
- @Override
- public void stackTraceRequested() {
- stacktrace.call(new Type[0], new IValue[0], null);
- }
-
- @Override
- public void initialize(InputStream input, OutputStream stdout, OutputStream stderr, IDEServices services) {
- this.stdout = stdout;
- this.stderr = stderr;
- this.input = input;
- }
-
@Override
public String getPrompt() {
return currentPrompt;
}
@Override
- public void handleInput(String line, Map output, Map metadata) throws InterruptedException {
-
+ public ICommandOutput handleInput(String line) throws InterruptedException {
if (line.trim().equals(quit)) {
- throw new InterruptedException(quit);
+ throw new EndOfFileException();
}
- else {
- try {
- handler.getEval().__setInterrupt(false);
- IConstructor content = (IConstructor) call(handler, new Type[] { tf.stringType() }, new IValue[] { vf.string(line) });
+ try {
+ handler.getEval().__setInterrupt(false);
+ IConstructor content = (IConstructor) call(handler, new Type[] { tf.stringType() }, new IValue[] { vf.string(line) });
- if (content.has("id")) {
- handleInteractiveContent(output, metadata, content);
- }
- else {
- IConstructor response = (IConstructor) content.get("response");
- switch (response.getName()) {
- case "response":
- handlePlainTextResponse(output, response);
- break;
- case "fileResponse":
- handleFileResponse(output, response);
- break;
- case "jsonResponse":
- handleJSONResponse(output, response);
- }
+ if (content.has("id")) {
+ return handleInteractiveContent(content);
+ }
+ else {
+ IConstructor response = (IConstructor) content.get("response");
+ switch (response.getName()) {
+ case "response":
+ return handlePlainTextResponse(response);
+ case "fileResponse":
+ return handleFileResponse(response);
+ case "jsonResponse":
+ return handleJSONResponse(response);
+ default:
+ return errorResponse("Unexpected constructor: " + response.getName());
}
}
- catch (IOException e) {
- output.put("text/plain", new ByteArrayInputStream(e.getMessage().getBytes()));
+ }
+ catch (IOException e) {
+ return errorResponse(e.getMessage());
+ }
+ catch (Throwable e) {
+ return errorResponse(e.getMessage());
+ }
+ }
+
+ private ICommandOutput errorResponse(String message) {
+ return new IErrorCommandOutput() {
+ @Override
+ public ICommandOutput getError() {
+ return () -> new AsciiStringOutputPrinter(message);
}
- catch (Throwable e) {
- output.put("text/plain", new ByteArrayInputStream(e.getMessage() != null ? e.getMessage().getBytes() : e.getClass().getName().getBytes()));
+ @Override
+ public IOutputPrinter asPlain() {
+ return new AsciiStringOutputPrinter(message);
}
- }
+ };
}
+
- private void handleInteractiveContent(Map output, Map metadata,
- IConstructor content) throws IOException, UnsupportedEncodingException {
+ private ICommandOutput handleInteractiveContent(IConstructor content) throws IOException, UnsupportedEncodingException {
String id = ((IString) content.get("id")).getValue();
Function callback = liftProviderFunction(content.get("callback"));
REPLContentServer server = contentManager.addServer(id, callback);
- String URL = "http://localhost:" + server.getListeningPort();
-
- produceHTMLResponse(id, URL, output, metadata);
+ return produceHTMLResponse(id, URIUtil.assumeCorrect("http", "localhost:" + server.getListeningPort(), ""));
}
+
+ abstract class NotebookWebContentOutput implements INotebookOutput, IWebContentOutput {}
- private void produceHTMLResponse(String id, String URL, Map output, Map metadata) throws UnsupportedEncodingException{
- String html;
- if (metadata.containsKey("origin") && metadata.get("origin").equals("notebook"))
- html = " \n \n
";
- else
- html = "";
-
- metadata.put("url", URL);
+ private ICommandOutput produceHTMLResponse(String id, URI URL) throws UnsupportedEncodingException{
+ return new NotebookWebContentOutput() {
+ @Override
+ public IOutputPrinter asNotebook() {
+ return new IOutputPrinter() {
+ @Override
+ public void write(PrintWriter target, boolean unicodeSupported) {
+ target.println("