summaryrefslogtreecommitdiff
path: root/src/repl
diff options
context:
space:
mode:
authorLukas Rytz <lukas.rytz@typesafe.com>2014-11-07 09:07:43 +0100
committerLukas Rytz <lukas.rytz@typesafe.com>2014-11-07 09:07:43 +0100
commitf7c3c6bc37228a70e06d5542ed4927bf3614486f (patch)
tree5b023cb22f6fb3048e26de1dfadc8c4fcca51d21 /src/repl
parent838ff2c2f256d1c114a406ff1032be92a3d3dac6 (diff)
parent126effe46005673ca826045e9cb037096d68af90 (diff)
downloadscala-f7c3c6bc37228a70e06d5542ed4927bf3614486f.tar.gz
scala-f7c3c6bc37228a70e06d5542ed4927bf3614486f.tar.bz2
scala-f7c3c6bc37228a70e06d5542ed4927bf3614486f.zip
Merge pull request #4058 from som-snytt/issue/verbose-load
SI-8922 REPL load -v
Diffstat (limited to 'src/repl')
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ILoop.scala65
-rw-r--r--src/repl/scala/tools/nsc/interpreter/LoopCommands.scala4
-rw-r--r--src/repl/scala/tools/nsc/interpreter/SimpleReader.scala29
3 files changed, 64 insertions, 34 deletions
diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
index 6e18682494..1c751c8a9f 100644
--- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
@@ -392,23 +392,23 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
true
}
+ // after process line, OK continue, ERR break, or EOF all done
+ object LineResults extends Enumeration {
+ type LineResult = Value
+ val EOF, ERR, OK = Value
+ }
+ import LineResults.LineResult
+
// return false if repl should exit
def processLine(line: String): Boolean = {
import scala.concurrent.duration._
Await.ready(globalFuture, 10.minutes) // Long timeout here to avoid test failures under heavy load.
- if (line eq null) {
- // SI-4563: this means the console was properly interrupted (Ctrl+D usually)
- // so we display the output message (which by default ends with
- // a newline so as not to break the user's terminal)
- if (in.interactive) out.print(Properties.shellInterruptedString)
-
- false
- } else (command(line) match {
+ command(line) match {
case Result(false, _) => false
case Result(_, Some(line)) => addReplay(line) ; true
case _ => true
- })
+ }
}
private def readOneLine() = {
@@ -426,18 +426,22 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
* command() for each line of input, and stops when
* command() returns false.
*/
- @tailrec final def loop() {
- if ( try processLine(readOneLine()) catch crashRecovery )
- loop()
+ @tailrec final def loop(): LineResult = {
+ import LineResults._
+ readOneLine() match {
+ case null => EOF
+ case line => if (try processLine(line) catch crashRecovery) loop() else ERR
+ }
}
/** interpret all lines from a specified file */
- def interpretAllFrom(file: File) {
+ def interpretAllFrom(file: File, verbose: Boolean = false) {
savingReader {
savingReplayStack {
file applyReader { reader =>
- in = SimpleReader(reader, out, interactive = false)
- echo("Loading " + file + "...")
+ in = if (verbose) new SimpleReader(reader, out, interactive = true) with EchoReader
+ else SimpleReader(reader, out, interactive = false)
+ echo(s"Loading $file...")
loop()
}
}
@@ -592,13 +596,17 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
res
}
- def loadCommand(arg: String) = {
- var shouldReplay: Option[String] = None
- withFile(arg)(f => {
- interpretAllFrom(f)
- shouldReplay = Some(":load " + arg)
- })
- Result(keepRunning = true, shouldReplay)
+ def loadCommand(arg: String): Result = {
+ def run(file: String, verbose: Boolean) = withFile(file) { f =>
+ interpretAllFrom(f, verbose)
+ Result recording s":load $arg"
+ } getOrElse Result.default
+
+ words(arg) match {
+ case "-v" :: file :: Nil => run(file, verbose = true)
+ case file :: Nil => run(file, verbose = false)
+ case _ => echo("usage: :load -v file") ; Result.default
+ }
}
def saveCommand(filename: String): Result = (
@@ -685,13 +693,13 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
}
val code = file match {
case Some(name) =>
- withFile(name)(f => {
+ withFile(name) { f =>
shouldReplay = Some(s":paste $arg")
val s = f.slurp.trim
if (s.isEmpty) echo(s"File contains no code: $f")
else echo(s"Pasting file $f...")
s
- }) getOrElse ""
+ } getOrElse ""
case None =>
echo("// Entering paste mode (ctrl-D to finish)\n")
val text = (readWhile(_ => true) mkString "\n").trim
@@ -820,7 +828,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
)
catch {
case ex @ (_: Exception | _: NoClassDefFoundError) =>
- echo("Failed to created JLineReader: " + ex + "\nFalling back to SimpleReader.")
+ echo(f"Failed to created JLineReader: ${ex}%nFalling back to SimpleReader.")
SimpleReader()
}
}
@@ -847,6 +855,8 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
case _ =>
}
}
+
+ // start an interpreter with the given settings
def process(settings: Settings): Boolean = savingContextLoader {
this.settings = settings
createInterpreter()
@@ -861,7 +871,10 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
loadFiles(settings)
printWelcome()
- try loop()
+ try loop() match {
+ case LineResults.EOF => out print Properties.shellInterruptedString
+ case _ =>
+ }
catch AbstractOrMissingHandler()
finally closeInterpreter()
diff --git a/src/repl/scala/tools/nsc/interpreter/LoopCommands.scala b/src/repl/scala/tools/nsc/interpreter/LoopCommands.scala
index 12d6ee5112..f177816b30 100644
--- a/src/repl/scala/tools/nsc/interpreter/LoopCommands.scala
+++ b/src/repl/scala/tools/nsc/interpreter/LoopCommands.scala
@@ -76,6 +76,9 @@ trait LoopCommands {
// the default result means "keep running, and don't record that line"
val default = Result(keepRunning = true, None)
+ // "keep running, and record this line"
+ def recording(line: String) = Result(keepRunning = true, Option(line))
+
// most commands do not want to micromanage the Result, but they might want
// to print something to the console, so we accomodate Unit and String returns.
implicit def resultFromUnit(x: Unit): Result = default
@@ -85,4 +88,3 @@ trait LoopCommands {
}
}
}
-
diff --git a/src/repl/scala/tools/nsc/interpreter/SimpleReader.scala b/src/repl/scala/tools/nsc/interpreter/SimpleReader.scala
index 6634dc6944..49b8433a8c 100644
--- a/src/repl/scala/tools/nsc/interpreter/SimpleReader.scala
+++ b/src/repl/scala/tools/nsc/interpreter/SimpleReader.scala
@@ -22,14 +22,19 @@ extends InteractiveReader
def reset() = ()
def redrawLine() = ()
- def readOneLine(prompt: String): String = {
- if (interactive) {
- out.print(prompt)
- out.flush()
- }
- in.readLine()
+
+ // InteractiveReader internals
+ protected def readOneLine(prompt: String): String = {
+ echo(prompt)
+ readOneLine()
+ }
+ protected def readOneKey(prompt: String) = sys.error("No char-based input in SimpleReader")
+
+ protected def readOneLine(): String = in.readLine()
+ protected def echo(s: String): Unit = if (interactive) {
+ out.print(s)
+ out.flush()
}
- def readOneKey(prompt: String) = sys.error("No char-based input in SimpleReader")
}
object SimpleReader {
@@ -39,3 +44,13 @@ object SimpleReader {
def apply(in: BufferedReader = defaultIn, out: JPrintWriter = defaultOut, interactive: Boolean = true): SimpleReader =
new SimpleReader(in, out, interactive)
}
+
+// pretend we are a console for verbose purposes
+trait EchoReader extends SimpleReader {
+ // if there is more input, then maybe echo the prompt and the input
+ override def readOneLine(prompt: String) = {
+ val input = readOneLine()
+ if (input != null) echo(f"$prompt$input%n")
+ input
+ }
+}