[cli-repl] Create wrapper for console reader

This commit is contained in:
Dmitry Kovanikov
2015-09-18 13:57:54 +03:00
committed by Pavel V. Talanov
parent 4aa5a90370
commit 18304c7d7b
5 changed files with 104 additions and 50 deletions
@@ -18,21 +18,19 @@ package org.jetbrains.kotlin.cli.jvm.repl;
import com.intellij.openapi.Disposable;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.testFramework.LightVirtualFile;
import jline.console.ConsoleReader;
import jline.console.history.FileHistory;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.cli.common.KotlinVersion;
import org.jetbrains.kotlin.cli.jvm.repl.messages.IdeLinebreaksUnescaper;
import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplErrorLogger;
import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplSystemInWrapper;
import org.jetbrains.kotlin.cli.jvm.repl.messages.ReplSystemOutWrapper;
import org.jetbrains.kotlin.cli.jvm.repl.reader.ConsoleReplCommandReader;
import org.jetbrains.kotlin.cli.jvm.repl.reader.IdeReplCommandReader;
import org.jetbrains.kotlin.cli.jvm.repl.reader.ReplCommandReader;
import org.jetbrains.kotlin.config.CompilerConfiguration;
import org.jetbrains.kotlin.utils.UtilsPackage;
import java.io.*;
import java.io.File;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.List;
@@ -47,7 +45,7 @@ public class ReplFromTerminal {
private final ReplSystemOutWrapper replWriter;
private final ReplErrorLogger replErrorLogger;
private ConsoleReader consoleReader;
private ReplCommandReader commandReader;
public ReplFromTerminal(
@NotNull final Disposable disposable,
@@ -87,24 +85,19 @@ public class ReplFromTerminal {
}.start();
try {
OutputStream outStream = System.out;
if (ideMode) {
// consoleReader duplicates his input in his output stream;
// to prevent such behaviour we redirect his output to dummy output stream
VirtualFile consoleOutputRedirect = new LightVirtualFile("kotlinConsoleReplRedirect");
outStream = consoleOutputRedirect.getOutputStream(null);
}
consoleReader = new ConsoleReader("kotlin", System.in, outStream, null);
consoleReader.setHistoryEnabled(true);
consoleReader.setExpandEvents(false);
consoleReader.setHistory(new FileHistory(new File(new File(System.getProperty("user.home")), ".kotlin_history")));
commandReader = createCommandReader();
}
catch (Exception e) {
replErrorLogger.logException(e);
}
}
@NotNull
private ReplCommandReader createCommandReader() {
return ideMode ? new IdeReplCommandReader()
: new ConsoleReplCommandReader();
}
private ReplInterpreter getReplInterpreter() {
if (replInterpreter != null) {
return replInterpreter;
@@ -143,7 +136,9 @@ public class ReplFromTerminal {
}
finally {
try {
((FileHistory) consoleReader.getHistory()).flush();
if (commandReader instanceof ConsoleReplCommandReader) {
((ConsoleReplCommandReader) commandReader).getFileHistory().flush();
}
}
catch (Exception e) {
replErrorLogger.logException(e);
@@ -160,8 +155,8 @@ public class ReplFromTerminal {
@NotNull
private WhatNextAfterOneLine one(@NotNull WhatNextAfterOneLine next) {
try {
String prompt = getPrompt(next);
String line = readLine(prompt);
String prompt = next == WhatNextAfterOneLine.INCOMPLETE ? "... " : ">>> ";
String line = commandReader.readLine(prompt);
if (line == null) {
return WhatNextAfterOneLine.QUIT;
@@ -185,25 +180,6 @@ public class ReplFromTerminal {
}
}
@Nullable
private String getPrompt(@NotNull WhatNextAfterOneLine next) {
String prompt = null;
// consoleReader always print prompt; in [ideMode] we don't allow it
if (!ideMode) {
prompt = next == WhatNextAfterOneLine.INCOMPLETE ? "... " : ">>> ";
}
return prompt;
}
@Nullable
private String readLine(@Nullable String prompt) throws IOException {
String line = consoleReader.readLine(prompt);
if (ideMode && line != null) {
line = IdeLinebreaksUnescaper.unescapeFromDiez(line).trim();
}
return line;
}
@NotNull
private ReplInterpreter.LineResultType eval(@NotNull String line) {
ReplInterpreter.LineResult lineResult = getReplInterpreter().eval(line);
@@ -24,7 +24,7 @@ public class ReplSystemInWrapper(
private val replWriter: ReplSystemOutWrapper
) : InputStream() {
private var isXmlIncomplete = true
private var isLastScriptByteProcessed = false
private var isLastByteProcessed = false
private var isReadLineStartSent = false
private var byteBuilder = ByteArrayOutputStream()
private var curBytePos = 0
@@ -36,10 +36,13 @@ public class ReplSystemInWrapper(
var isReplScriptExecuting = false
override fun read(): Int {
if (isLastScriptByteProcessed && isReplScriptExecuting) {
isLastScriptByteProcessed = false
isReadLineStartSent = false
replWriter.printlnReadLineEnd()
if (isLastByteProcessed) {
if (isReplScriptExecuting) {
isReadLineStartSent = false
replWriter.printlnReadLineEnd()
}
isLastByteProcessed = false
return -1
}
@@ -53,7 +56,7 @@ public class ReplSystemInWrapper(
if (byteBuilder.toString().endsWith(END_LINE)) {
isXmlIncomplete = false
isLastScriptByteProcessed = false
isLastByteProcessed = false
inputByteArray = unescapedInput().toByteArray()
}
@@ -81,8 +84,7 @@ public class ReplSystemInWrapper(
isXmlIncomplete = true
byteBuilder = ByteArrayOutputStream()
curBytePos = 0
if (isReplScriptExecuting) isLastScriptByteProcessed = true
isLastByteProcessed = true
}
}
}
@@ -0,0 +1,34 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* 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.jetbrains.kotlin.cli.jvm.repl.reader
import jline.console.ConsoleReader
import jline.console.history.FileHistory
import java.io.File
public class ConsoleReplCommandReader : ReplCommandReader {
private val consoleReader = ConsoleReader("kotlin", System.`in`, System.`out`, null) apply {
isHistoryEnabled = true
expandEvents = false
history = FileHistory(File(File(System.getProperty("user.home")), ".kotlin_history"))
}
public val fileHistory: FileHistory
get() = consoleReader.history as FileHistory
override fun readLine(prompt: String?) = consoleReader.readLine(prompt)
}
@@ -0,0 +1,21 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* 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.jetbrains.kotlin.cli.jvm.repl.reader
public class IdeReplCommandReader : ReplCommandReader {
override fun readLine(prompt: String?) = readLine()
}
@@ -0,0 +1,21 @@
/*
* Copyright 2010-2015 JetBrains s.r.o.
*
* 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.jetbrains.kotlin.cli.jvm.repl.reader
public interface ReplCommandReader {
public fun readLine(prompt: String?): String?
}