summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ILoop.scala75
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Pasted.scala56
-rw-r--r--test/files/run/repl-paste-2.check2
-rw-r--r--test/files/run/repl-transcript.check2
4 files changed, 67 insertions, 68 deletions
diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
index 92655ba643..a0cc116df8 100644
--- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
@@ -24,9 +24,9 @@ import io.AbstractFile
import scala.collection.generic.Clearable
import scala.concurrent.{ ExecutionContext, Await, Future, future }
import ExecutionContext.Implicits._
-import java.io.{ BufferedReader, FileReader }
+import java.io.{ BufferedReader, FileReader, StringReader }
-import scala.util.{Try, Success, Failure}
+import scala.util.{ Try, Success, Failure }
/** The Scala interactive shell. It provides a read-eval-print loop
* around the Interpreter class.
@@ -748,28 +748,9 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
result
}
- private object paste extends Pasted {
- import scala.util.matching.Regex.quote
- val ContinuePrompt = replProps.continuePrompt
- val ContinueString = replProps.continueText // " | "
- val PromptString = prompt.lines.toList.last
- val anyPrompt = s"""\\s*(?:${quote(PromptString.trim)}|${quote(AltPromptString.trim)})\\s*""".r
-
- def isPrompted(line: String) = matchesPrompt(line)
- def isPromptOnly(line: String) = line match { case anyPrompt() => true ; case _ => false }
-
- def interpret(line: String): Unit = {
- echo(line.trim)
- intp interpret line
- echo("")
- }
-
- def transcript(start: String) = {
- echo("\n// Detected repl transcript paste: ctrl-D to finish.\n")
- apply(Iterator(start) ++ readWhile(!isPromptOnly(_)))
- }
-
- def unapply(line: String): Boolean = isPrompted(line)
+ private object paste extends Pasted(prompt) {
+ def interpret(line: String) = intp interpret line
+ def echo(message: String) = ILoop.this echo message
}
private object invocation {
@@ -784,30 +765,10 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
* read, go ahead and interpret it. Return the full string
* to be recorded for replay, if any.
*/
- def interpretStartingWith(code: String): Option[String] = {
+ @tailrec final def interpretStartingWith(code: String): Option[String] = {
// signal completion non-completion input has been received
in.completion.resetVerbosity()
- def reallyInterpret = intp.interpret(code) match {
- case IR.Error => None
- case IR.Success => Some(code)
- case IR.Incomplete if in.interactive && code.endsWith("\n\n") =>
- echo("You typed two blank lines. Starting a new command.")
- None
- case IR.Incomplete =>
- in.readLine(paste.ContinuePrompt) match {
- case null =>
- // we know compilation is going to fail since we're at EOF and the
- // parser thinks the input is still incomplete, but since this is
- // a file being read non-interactively we want to fail. So we send
- // it straight to the compiler for the nice error message.
- intp.compileString(code)
- None
-
- case line => interpretStartingWith(code + "\n" + line)
- }
- }
-
/* Here we place ourselves between the user and the interpreter and examine
* the input they are ostensibly submitting. We intervene in several cases:
*
@@ -820,9 +781,29 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
code match {
case "" => None
case lineComment() => None // line comment, do nothing
- case paste() if !paste.running => paste.transcript(code) ; None
+ case paste() if !paste.running => paste.transcript(Iterator(code) ++ readWhile(!paste.isPromptOnly(_))) match {
+ case Some(s) => interpretStartingWith(s)
+ case _ => None
+ }
case invocation() if intp.mostRecentVar != "" => interpretStartingWith(intp.mostRecentVar + code)
- case _ => reallyInterpret
+ case _ => intp.interpret(code) match {
+ case IR.Error => None
+ case IR.Success => Some(code)
+ case IR.Incomplete if in.interactive && code.endsWith("\n\n") =>
+ echo("You typed two blank lines. Starting a new command.")
+ None
+ case IR.Incomplete => in.readLine(paste.ContinuePrompt) match {
+ case null =>
+ // we know compilation is going to fail since we're at EOF and the
+ // parser thinks the input is still incomplete, but since this is
+ // a file being read non-interactively we want to fail. So we send
+ // it straight to the compiler for the nice error message.
+ intp.compileString(code)
+ None
+
+ case line => interpretStartingWith(s"$code\n$line")
+ }
+ }
}
}
diff --git a/src/repl/scala/tools/nsc/interpreter/Pasted.scala b/src/repl/scala/tools/nsc/interpreter/Pasted.scala
index f8d8c2ddb1..3a7eda1b77 100644
--- a/src/repl/scala/tools/nsc/interpreter/Pasted.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Pasted.scala
@@ -15,19 +15,23 @@ package interpreter
* a transcript should itself be pasteable and should achieve
* the same result.
*/
-abstract class Pasted {
- def interpret(line: String): Unit
- def ContinueString: String
- def PromptString: String
- def AltPromptString: String = "scala> "
+abstract class Pasted(prompt: String) {
+ def interpret(line: String): IR.Result
+ def echo(message: String): Unit
- /* `testBoth` cannot be a val, as `Pasted` is inherited by `object paste` in ILoop,
- which would cause `val testBoth` to be initialized before `val PromptString` was.
+ val PromptString = prompt.lines.toList.last
+ val AltPromptString = "scala> "
+ val ContinuePrompt = replProps.continuePrompt
+ val ContinueString = replProps.continueText // " | "
+ val anyPrompt = {
+ import scala.util.matching.Regex.quote
+ s"""\\s*(?:${quote(PromptString.trim)}|${quote(AltPromptString.trim)})\\s*""".r
+ }
+
+ def isPrompted(line: String) = matchesPrompt(line)
+ def isPromptOnly(line: String) = line match { case anyPrompt() => true ; case _ => false }
- object paste extends Pasted {
- val PromptString = prompt.lines.toList.last
- */
- private def testBoth = PromptString != AltPromptString
+ private val testBoth = PromptString != AltPromptString
private val spacey = " \t".toSet
def matchesPrompt(line: String) = matchesString(line, PromptString) || testBoth && matchesString(line, AltPromptString)
@@ -91,13 +95,26 @@ abstract class Pasted {
case _ => code
}
- def run(): Unit = {
- println("// Replaying %d commands from transcript.\n" format cmds.size)
- cmds foreach { cmd =>
- print(ActualPromptString)
- interpret(cmd)
- }
+ def interpreted(line: String) = {
+ echo(line.trim)
+ val res = interpret(line)
+ if (res != IR.Incomplete) echo("")
+ res
+ }
+ def incompletely(cmd: String) = {
+ print(ActualPromptString)
+ interpreted(cmd) == IR.Incomplete
}
+ def run(): Option[String] = {
+ echo(s"// Replaying ${cmds.size} commands from transcript.\n")
+ cmds find incompletely
+ }
+ }
+
+ // Run transcript and return incomplete line if any.
+ def transcript(lines: TraversableOnce[String]): Option[String] = {
+ echo("\n// Detected repl transcript. Paste more, or ctrl-D to finish.\n")
+ apply(lines)
}
/** Commands start on lines beginning with "scala>" and each successive
@@ -105,9 +122,10 @@ abstract class Pasted {
* Everything else is discarded. When the end of the transcript is spotted,
* all the commands are replayed.
*/
- def apply(lines: TraversableOnce[String]) = {
+ def apply(lines: TraversableOnce[String]): Option[String] = {
isRunning = true
- try new PasteAnalyzer(lines.toList) run()
+ try new PasteAnalyzer(lines.toList).run()
finally isRunning = false
}
+ def unapply(line: String): Boolean = isPrompted(line)
}
diff --git a/test/files/run/repl-paste-2.check b/test/files/run/repl-paste-2.check
index dbf5363c0f..4c589df41a 100644
--- a/test/files/run/repl-paste-2.check
+++ b/test/files/run/repl-paste-2.check
@@ -1,7 +1,7 @@
scala> scala> 999l
-// Detected repl transcript paste: ctrl-D to finish.
+// Detected repl transcript. Paste more, or ctrl-D to finish.
res4: Int = 0123
diff --git a/test/files/run/repl-transcript.check b/test/files/run/repl-transcript.check
index 762a96b9cc..d0b455cbf6 100644
--- a/test/files/run/repl-transcript.check
+++ b/test/files/run/repl-transcript.check
@@ -1,7 +1,7 @@
scala> scala> class Bippity
-// Detected repl transcript paste: ctrl-D to finish.
+// Detected repl transcript. Paste more, or ctrl-D to finish.
defined class Bippity