Skip to content

Commit f7c3c6b

Browse files
committed
Merge pull request scala#4058 from som-snytt/issue/verbose-load
SI-8922 REPL load -v
2 parents 838ff2c + 126effe commit f7c3c6b

File tree

4 files changed

+67
-35
lines changed

4 files changed

+67
-35
lines changed

src/compiler/scala/tools/nsc/Properties.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,9 @@ object Properties extends scala.util.PropertiesTrait {
1414
// settings based on jar properties, falling back to System prefixed by "scala."
1515
def residentPromptString = scalaPropOrElse("resident.prompt", "\nnsc> ")
1616
def shellPromptString = scalaPropOrElse("shell.prompt", "\nscala> ")
17-
def shellInterruptedString = scalaPropOrElse("shell.interrupted", ":quit\n")
17+
// message to display at EOF (which by default ends with
18+
// a newline so as not to break the user's terminal)
19+
def shellInterruptedString = scalaPropOrElse("shell.interrupted", f":quit$lineSeparator")
1820

1921
// derived values
2022
def isEmacsShell = propOrEmpty("env.emacs") != ""

src/repl/scala/tools/nsc/interpreter/ILoop.scala

Lines changed: 39 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -392,23 +392,23 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
392392
true
393393
}
394394

395+
// after process line, OK continue, ERR break, or EOF all done
396+
object LineResults extends Enumeration {
397+
type LineResult = Value
398+
val EOF, ERR, OK = Value
399+
}
400+
import LineResults.LineResult
401+
395402
// return false if repl should exit
396403
def processLine(line: String): Boolean = {
397404
import scala.concurrent.duration._
398405
Await.ready(globalFuture, 10.minutes) // Long timeout here to avoid test failures under heavy load.
399406

400-
if (line eq null) {
401-
// SI-4563: this means the console was properly interrupted (Ctrl+D usually)
402-
// so we display the output message (which by default ends with
403-
// a newline so as not to break the user's terminal)
404-
if (in.interactive) out.print(Properties.shellInterruptedString)
405-
406-
false
407-
} else (command(line) match {
407+
command(line) match {
408408
case Result(false, _) => false
409409
case Result(_, Some(line)) => addReplay(line) ; true
410410
case _ => true
411-
})
411+
}
412412
}
413413

414414
private def readOneLine() = {
@@ -426,18 +426,22 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
426426
* command() for each line of input, and stops when
427427
* command() returns false.
428428
*/
429-
@tailrec final def loop() {
430-
if ( try processLine(readOneLine()) catch crashRecovery )
431-
loop()
429+
@tailrec final def loop(): LineResult = {
430+
import LineResults._
431+
readOneLine() match {
432+
case null => EOF
433+
case line => if (try processLine(line) catch crashRecovery) loop() else ERR
434+
}
432435
}
433436

434437
/** interpret all lines from a specified file */
435-
def interpretAllFrom(file: File) {
438+
def interpretAllFrom(file: File, verbose: Boolean = false) {
436439
savingReader {
437440
savingReplayStack {
438441
file applyReader { reader =>
439-
in = SimpleReader(reader, out, interactive = false)
440-
echo("Loading " + file + "...")
442+
in = if (verbose) new SimpleReader(reader, out, interactive = true) with EchoReader
443+
else SimpleReader(reader, out, interactive = false)
444+
echo(s"Loading $file...")
441445
loop()
442446
}
443447
}
@@ -592,13 +596,17 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
592596
res
593597
}
594598

595-
def loadCommand(arg: String) = {
596-
var shouldReplay: Option[String] = None
597-
withFile(arg)(f => {
598-
interpretAllFrom(f)
599-
shouldReplay = Some(":load " + arg)
600-
})
601-
Result(keepRunning = true, shouldReplay)
599+
def loadCommand(arg: String): Result = {
600+
def run(file: String, verbose: Boolean) = withFile(file) { f =>
601+
interpretAllFrom(f, verbose)
602+
Result recording s":load $arg"
603+
} getOrElse Result.default
604+
605+
words(arg) match {
606+
case "-v" :: file :: Nil => run(file, verbose = true)
607+
case file :: Nil => run(file, verbose = false)
608+
case _ => echo("usage: :load -v file") ; Result.default
609+
}
602610
}
603611

604612
def saveCommand(filename: String): Result = (
@@ -685,13 +693,13 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
685693
}
686694
val code = file match {
687695
case Some(name) =>
688-
withFile(name)(f => {
696+
withFile(name) { f =>
689697
shouldReplay = Some(s":paste $arg")
690698
val s = f.slurp.trim
691699
if (s.isEmpty) echo(s"File contains no code: $f")
692700
else echo(s"Pasting file $f...")
693701
s
694-
}) getOrElse ""
702+
} getOrElse ""
695703
case None =>
696704
echo("// Entering paste mode (ctrl-D to finish)\n")
697705
val text = (readWhile(_ => true) mkString "\n").trim
@@ -820,7 +828,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
820828
)
821829
catch {
822830
case ex @ (_: Exception | _: NoClassDefFoundError) =>
823-
echo("Failed to created JLineReader: " + ex + "\nFalling back to SimpleReader.")
831+
echo(f"Failed to created JLineReader: ${ex}%nFalling back to SimpleReader.")
824832
SimpleReader()
825833
}
826834
}
@@ -847,6 +855,8 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
847855
case _ =>
848856
}
849857
}
858+
859+
// start an interpreter with the given settings
850860
def process(settings: Settings): Boolean = savingContextLoader {
851861
this.settings = settings
852862
createInterpreter()
@@ -861,7 +871,10 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
861871
loadFiles(settings)
862872
printWelcome()
863873

864-
try loop()
874+
try loop() match {
875+
case LineResults.EOF => out print Properties.shellInterruptedString
876+
case _ =>
877+
}
865878
catch AbstractOrMissingHandler()
866879
finally closeInterpreter()
867880

src/repl/scala/tools/nsc/interpreter/LoopCommands.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ trait LoopCommands {
7676
// the default result means "keep running, and don't record that line"
7777
val default = Result(keepRunning = true, None)
7878

79+
// "keep running, and record this line"
80+
def recording(line: String) = Result(keepRunning = true, Option(line))
81+
7982
// most commands do not want to micromanage the Result, but they might want
8083
// to print something to the console, so we accomodate Unit and String returns.
8184
implicit def resultFromUnit(x: Unit): Result = default
@@ -85,4 +88,3 @@ trait LoopCommands {
8588
}
8689
}
8790
}
88-

src/repl/scala/tools/nsc/interpreter/SimpleReader.scala

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,14 +22,19 @@ extends InteractiveReader
2222

2323
def reset() = ()
2424
def redrawLine() = ()
25-
def readOneLine(prompt: String): String = {
26-
if (interactive) {
27-
out.print(prompt)
28-
out.flush()
29-
}
30-
in.readLine()
25+
26+
// InteractiveReader internals
27+
protected def readOneLine(prompt: String): String = {
28+
echo(prompt)
29+
readOneLine()
30+
}
31+
protected def readOneKey(prompt: String) = sys.error("No char-based input in SimpleReader")
32+
33+
protected def readOneLine(): String = in.readLine()
34+
protected def echo(s: String): Unit = if (interactive) {
35+
out.print(s)
36+
out.flush()
3137
}
32-
def readOneKey(prompt: String) = sys.error("No char-based input in SimpleReader")
3338
}
3439

3540
object SimpleReader {
@@ -39,3 +44,13 @@ object SimpleReader {
3944
def apply(in: BufferedReader = defaultIn, out: JPrintWriter = defaultOut, interactive: Boolean = true): SimpleReader =
4045
new SimpleReader(in, out, interactive)
4146
}
47+
48+
// pretend we are a console for verbose purposes
49+
trait EchoReader extends SimpleReader {
50+
// if there is more input, then maybe echo the prompt and the input
51+
override def readOneLine(prompt: String) = {
52+
val input = readOneLine()
53+
if (input != null) echo(f"$prompt$input%n")
54+
input
55+
}
56+
}

0 commit comments

Comments
 (0)