Skip to content
This repository was archived by the owner on Sep 1, 2020. It is now read-only.

Commit 3bfafbc

Browse files
committed
SI-9206 Accept paste with custom prompt
But sans test.
1 parent a9053f4 commit 3bfafbc

File tree

4 files changed

+41
-24
lines changed

4 files changed

+41
-24
lines changed

src/partest-extras/scala/tools/partest/ReplTest.scala

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -75,18 +75,20 @@ abstract class SessionTest extends ReplTest {
7575
* Retain user input: prompt lines and continuations, without the prefix; or pasted text plus ctl-D.
7676
*/
7777
import SessionTest._
78-
override final def code = input findAllMatchIn (expected mkString ("", "\n", "\n")) map {
79-
case input(null, null, prompted) =>
78+
lazy val pasted = input(prompt)
79+
override final def code = pasted findAllMatchIn (expected mkString ("", "\n", "\n")) map {
80+
case pasted(null, null, prompted) =>
8081
def continued(m: Match): Option[String] = m match {
8182
case margin(text) => Some(text)
8283
case _ => None
8384
}
8485
margin.replaceSomeIn(prompted, continued)
85-
case input(cmd, pasted, null) =>
86+
case pasted(cmd, pasted, null) =>
8687
cmd + pasted + "\u0004"
8788
} mkString
8889

89-
final def prompt = "scala> "
90+
// Just the last line of the interactive prompt
91+
def prompt = "scala> "
9092

9193
/** Default test is to compare expected and actual output and emit the diff on a failed comparison. */
9294
override def show() = {
@@ -98,7 +100,7 @@ abstract class SessionTest extends ReplTest {
98100
}
99101
object SessionTest {
100102
// \R for line break is Java 8, \v for vertical space might suffice
101-
val input = """(?m)^scala> (:pa.*\u000A)// Entering paste mode.*\u000A\u000A((?:.*\u000A)*)\u000A// Exiting paste mode.*\u000A|^scala> (.*\u000A(?:\s*\| .*\u000A)*)""".r
103+
def input(prompt: String) = s"""(?m)^$prompt(:pa.*\u000A)// Entering paste mode.*\u000A\u000A((?:.*\u000A)*)\u000A// Exiting paste mode.*\u000A|^scala> (.*\u000A(?:\\s*\\| .*\u000A)*)""".r
102104

103105
val margin = """(?m)^\s*\| (.*)$""".r
104106
}

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

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -765,16 +765,13 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
765765
}
766766

767767
private object paste extends Pasted {
768+
import scala.util.matching.Regex.quote
768769
val ContinueString = " | "
769-
val PromptString = "scala> "
770-
val testPrompt = PromptString.trim
771-
val testOurPrompt = prompt.trim
772-
val testBoth = testPrompt != testOurPrompt
770+
val PromptString = prompt.lines.toList.last
771+
val anyPrompt = s"""\\s*(?:${quote(PromptString.trim)}|${quote(AltPromptString.trim)})\\s*""".r
773772

774-
def isPrompt(line: String) = {
775-
val text = line.trim
776-
text == testOurPrompt || (testBoth && text == testPrompt)
777-
}
773+
def isPrompted(line: String) = matchesPrompt(line)
774+
def isPromptOnly(line: String) = line match { case anyPrompt() => true ; case _ => false }
778775

779776
def interpret(line: String): Unit = {
780777
echo(line.trim)
@@ -784,10 +781,9 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
784781

785782
def transcript(start: String) = {
786783
echo("\n// Detected repl transcript paste: ctrl-D to finish.\n")
787-
apply(Iterator(start) ++ readWhile(!isPrompt(_)))
784+
apply(Iterator(start) ++ readWhile(!isPromptOnly(_)))
788785
}
789786
}
790-
import paste.{ ContinueString, PromptString }
791787

792788
/** Interpret expressions starting with the first line.
793789
* Read lines until a complete compilation unit is available
@@ -809,7 +805,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
809805
echo("You typed two blank lines. Starting a new command.")
810806
None
811807
}
812-
else in.readLine(ContinueString) match {
808+
else in.readLine(paste.ContinueString) match {
813809
case null =>
814810
// we know compilation is going to fail since we're at EOF and the
815811
// parser thinks the input is still incomplete, but since this is
@@ -833,7 +829,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
833829
* and avoid the interpreter, as it's likely not valid scala code.
834830
*/
835831
if (code == "") None
836-
else if (!paste.running && code.trim.startsWith(PromptString)) {
832+
else if (!paste.running && paste.isPrompted(code)) {
837833
paste.transcript(code)
838834
None
839835
}

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

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,21 @@ package interpreter
1616
* the same result.
1717
*/
1818
abstract class Pasted {
19+
def interpret(line: String): Unit
1920
def ContinueString: String
2021
def PromptString: String
21-
def interpret(line: String): Unit
22+
def AltPromptString: String = "scala> "
23+
24+
private val testBoth = PromptString != AltPromptString
25+
private val spacey = " \t".toSet
2226

23-
def matchesPrompt(line: String) = matchesString(line, PromptString)
27+
def matchesPrompt(line: String) = matchesString(line, PromptString) || testBoth && matchesString(line, AltPromptString)
2428
def matchesContinue(line: String) = matchesString(line, ContinueString)
2529
def running = isRunning
2630

2731
private def matchesString(line: String, target: String): Boolean = (
2832
(line startsWith target) ||
29-
(line.nonEmpty && " \t".toSet(line.head) && matchesString(line.tail, target))
33+
(line.nonEmpty && spacey(line.head) && matchesString(line.tail, target))
3034
)
3135
private def stripString(line: String, target: String) = line indexOf target match {
3236
case -1 => line
@@ -39,7 +43,9 @@ abstract class Pasted {
3943

4044
private class PasteAnalyzer(val lines: List[String]) {
4145
val referenced = lines flatMap (resReference findAllIn _.trim.stripPrefix("res")) toSet
42-
val cmds = lines reduceLeft append split PromptString filterNot (_.trim == "") toList
46+
val ActualPromptString = lines find matchesPrompt map (s =>
47+
if (matchesString(s, PromptString)) PromptString else AltPromptString) getOrElse PromptString
48+
val cmds = lines reduceLeft append split ActualPromptString filterNot (_.trim == "") toList
4349

4450
/** If it's a prompt or continuation line, strip the formatting bits and
4551
* assemble the code. Otherwise ship it off to be analyzed for res references
@@ -67,10 +73,10 @@ abstract class Pasted {
6773
*/
6874
def fixResRefs(code: String, line: String) = line match {
6975
case resCreation(resName) if referenced(resName) =>
70-
code.lastIndexOf(PromptString) match {
76+
code.lastIndexOf(ActualPromptString) match {
7177
case -1 => code
7278
case idx =>
73-
val (str1, str2) = code splitAt (idx + PromptString.length)
79+
val (str1, str2) = code splitAt (idx + ActualPromptString.length)
7480
str2 match {
7581
case resAssign(`resName`) => code
7682
case _ => "%sval %s = { %s }".format(str1, resName, str2)
@@ -82,7 +88,7 @@ abstract class Pasted {
8288
def run() {
8389
println("// Replaying %d commands from transcript.\n" format cmds.size)
8490
cmds foreach { cmd =>
85-
print(PromptString)
91+
print(ActualPromptString)
8692
interpret(cmd)
8793
}
8894
}

test/files/run/t9206.scala

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import scala.tools.partest.SessionTest
33

44
object Test extends SessionTest {
5+
//override def prompt = "XXX> "
56
//Welcome to Scala version 2.11.6 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_40).
67
def session =
78
s"""|Type in expressions to have them evaluated.
@@ -22,5 +23,17 @@ object Test extends SessionTest {
2223
| ^
2324
|
2425
|scala> :quit"""
26+
/*
27+
|XXX> XXX> def f = 42
28+
|
29+
|// Detected repl transcript paste: ctrl-D to finish.
30+
|
31+
|// Replaying 1 commands from transcript.
32+
|
33+
|XXX> def f = 42
34+
|f: Int
35+
|
36+
|XXX> :quit"""
37+
*/
2538

2639
}

0 commit comments

Comments
 (0)