summaryrefslogtreecommitdiff
path: root/src/repl/scala/tools/nsc/interpreter/ILoop.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/repl/scala/tools/nsc/interpreter/ILoop.scala')
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ILoop.scala115
1 files changed, 51 insertions, 64 deletions
diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
index 6470a450b2..f844029b64 100644
--- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
@@ -1,8 +1,7 @@
/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
+ * Copyright 2005-2015 LAMP/EPFL
* @author Alexander Spoon
*/
-
package scala
package tools.nsc
package interpreter
@@ -24,9 +23,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.
@@ -658,12 +657,9 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
unleashAndSetPhase()
asyncEcho(isDuringInit, power.banner)
}
- private def unleashAndSetPhase() {
- if (isReplPower) {
- power.unleash()
- // Set the phase to "typer"
- intp beSilentDuring phaseCommand("typer")
- }
+ private def unleashAndSetPhase() = if (isReplPower) {
+ power.unleash()
+ intp beSilentDuring phaseCommand("typer") // Set the phase to "typer"
}
def asyncEcho(async: Boolean, msg: => String) {
@@ -751,28 +747,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 {
@@ -787,30 +764,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] = {
+ 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:
*
@@ -823,9 +780,33 @@ 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 =>
+ val saved = intp.partialInput
+ intp.partialInput = code + "\n"
+ try {
+ 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")
+ }
+ } finally intp.partialInput = saved
+ }
}
}
@@ -841,9 +822,10 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
case _ =>
}
- /** Tries to create a JLineReader, falling back to SimpleReader:
- * unless settings or properties are such that it should start
- * with SimpleReader.
+ /** Tries to create a JLineReader, falling back to SimpleReader,
+ * unless settings or properties are such that it should start with SimpleReader.
+ * The constructor of the InteractiveReader must take a Completion strategy,
+ * supplied as a `() => Completion`; the Completion object provides a concrete Completer.
*/
def chooseReader(settings: Settings): InteractiveReader = {
if (settings.Xnojline || Properties.isEmacsShell) SimpleReader()
@@ -851,20 +833,25 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
type Completer = () => Completion
type ReaderMaker = Completer => InteractiveReader
- def instantiate(className: String): ReaderMaker = completer => {
- if (settings.debug) Console.println(s"Trying to instantiate a InteractiveReader from $className")
+ def instantiater(className: String): ReaderMaker = completer => {
+ if (settings.debug) Console.println(s"Trying to instantiate an InteractiveReader from $className")
Class.forName(className).getConstructor(classOf[Completer]).
newInstance(completer).
asInstanceOf[InteractiveReader]
}
- def mkReader(maker: ReaderMaker) =
- if (settings.noCompletion) maker(() => NoCompletion)
- else maker(() => new JLineCompletion(intp)) // JLineCompletion is a misnomer -- it's not tied to jline
+ def mkReader(maker: ReaderMaker) = maker { () =>
+ settings.completion.value match {
+ case _ if settings.noCompletion => NoCompletion
+ case "none" => NoCompletion
+ case "adhoc" => new JLineCompletion(intp) // JLineCompletion is a misnomer; it's not tied to jline
+ case "pc" | _ => new PresentationCompilerCompleter(intp)
+ }
+ }
def internalClass(kind: String) = s"scala.tools.nsc.interpreter.$kind.InteractiveReader"
val readerClasses = sys.props.get("scala.repl.reader").toStream ++ Stream(internalClass("jline"), internalClass("jline_embedded"))
- val readers = readerClasses map (cls => Try { mkReader(instantiate(cls)) })
+ val readers = readerClasses map (cls => Try { mkReader(instantiater(cls)) })
val reader = (readers collect { case Success(reader) => reader } headOption) getOrElse SimpleReader()