summaryrefslogtreecommitdiff
path: root/src/compiler/scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala')
-rw-r--r--src/compiler/scala/tools/nsc/Interpreter.scala18
-rw-r--r--src/compiler/scala/tools/nsc/InterpreterLoop.scala28
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala1
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/JLineReader.scala5
4 files changed, 35 insertions, 17 deletions
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala
index e9474e973c..dd775d1a23 100644
--- a/src/compiler/scala/tools/nsc/Interpreter.scala
+++ b/src/compiler/scala/tools/nsc/Interpreter.scala
@@ -19,7 +19,7 @@ import io.{ PlainFile, VirtualDirectory, spawn, callable, newDaemonThreadExecuto
import reporters.{ ConsoleReporter, Reporter }
import symtab.{ Flags, Names }
import scala.tools.nsc.{ InterpreterResults => IR }
-import scala.tools.util.{ PathResolver, SignalManager }
+import scala.tools.util.PathResolver
import scala.tools.nsc.util.{ ScalaClassLoader, Exceptional }
import ScalaClassLoader.URLClassLoader
import Exceptional.unwrap
@@ -188,16 +188,8 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
/** An executor service which creates daemon threads. */
private lazy val lineExecutor = newDaemonThreadExecutor()
- private var currentExecution: Future[String] = null
- private def sigintHandler = {
- if (currentExecution == null) System.exit(1)
- else currentExecution.cancel(true)
- }
- /** Try to install sigint handler: false on failure. */
- def installSigIntHandler(): Boolean = {
- try { SignalManager("INT") = sigintHandler ; true }
- catch { case _: Exception => false }
- }
+ private var _currentExecution: Future[String] = null
+ def currentExecution = _currentExecution
/** interpreter settings */
lazy val isettings = new InterpreterSettings(this)
@@ -1033,7 +1025,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
def loadAndRun: (String, Boolean) = {
try {
val resultValMethod = loadedResultObject getMethod "scala_repl_result"
- currentExecution = lineExecutor submit callable(resultValMethod.invoke(loadedResultObject).toString)
+ _currentExecution = lineExecutor submit callable(resultValMethod.invoke(loadedResultObject).toString)
while (!currentExecution.isDone)
Thread.`yield`
@@ -1052,7 +1044,7 @@ class Interpreter(val settings: Settings, out: PrintWriter) {
}
}
finally {
- currentExecution = null
+ _currentExecution = null
}
}
diff --git a/src/compiler/scala/tools/nsc/InterpreterLoop.scala b/src/compiler/scala/tools/nsc/InterpreterLoop.scala
index bdcd7b9f58..a7f70b12b0 100644
--- a/src/compiler/scala/tools/nsc/InterpreterLoop.scala
+++ b/src/compiler/scala/tools/nsc/InterpreterLoop.scala
@@ -10,7 +10,9 @@ import java.io.{ BufferedReader, FileReader, PrintWriter }
import java.io.IOException
import scala.tools.nsc.{ InterpreterResults => IR }
+import scala.tools.util.SignalManager
import scala.annotation.tailrec
+import scala.util.control.Exception.{ ignoring }
import scala.collection.mutable.ListBuffer
import scala.concurrent.ops
import util.{ ClassPath }
@@ -102,6 +104,31 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
/** Record a command for replay should the user request a :replay */
def addReplay(cmd: String) = replayCommandStack ::= cmd
+ /** Try to install sigint handler: ignore failure. Signal handler
+ * will interrupt current line execution if any is in progress.
+ *
+ * Attempting to protect the repl from accidental exit, we only honor
+ * a single ctrl-C if the current buffer is empty: otherwise we look
+ * for a second one within a short time.
+ */
+ private def installSigIntHandler() {
+ def onExit() {
+ Console.println("") // avoiding "shell prompt in middle of line" syndrome
+ System.exit(1)
+ }
+ ignoring(classOf[Exception]) {
+ SignalManager("INT") = {
+ val exec = interpreter.currentExecution
+ if (exec != null) exec.cancel(true)
+ else if (in.currentLine != "") {
+ SignalManager("INT") = onExit()
+ io.timer(5)(installSigIntHandler()) // restore original
+ }
+ else onExit()
+ }
+ }
+ }
+
/** Close the interpreter and set the var to <code>null</code>. */
def closeInterpreter() {
if (interpreter ne null) {
@@ -121,6 +148,7 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
settings.explicitParentLoader.getOrElse( classOf[InterpreterLoop].getClassLoader )
}
interpreter.setContextClassLoader()
+ installSigIntHandler()
// interpreter.quietBind("settings", "scala.tools.nsc.InterpreterSettings", interpreter.isettings)
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala b/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
index 7e4abd1d76..840e457dd4 100644
--- a/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
@@ -17,6 +17,7 @@ trait InteractiveReader {
protected def readOneLine(prompt: String): String
val interactive: Boolean
def init(): Unit = ()
+ def currentLine = "" // the current buffer contents, if available
def readLine(prompt: String): String = {
def handler: Catcher[String] = {
diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala b/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
index f73df48fea..1da96de0d9 100644
--- a/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
@@ -17,10 +17,6 @@ class JLineReader(interpreter: Interpreter) extends InteractiveReader {
override lazy val completion = Option(interpreter) map (x => new Completion(x))
override def init() = consoleReader.getTerminal().initializeTerminal()
- locally {
- interpreter.installSigIntHandler()
- }
-
val consoleReader = {
val r = new jline.ConsoleReader()
r setHistory (History().jhistory)
@@ -33,6 +29,7 @@ class JLineReader(interpreter: Interpreter) extends InteractiveReader {
r
}
+ override def currentLine: String = consoleReader.getCursorBuffer.getBuffer.toString
def readOneLine(prompt: String) = consoleReader readLine prompt
val interactive = true
}