summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorSom Snytt <som.snytt@gmail.com>2015-06-20 13:52:34 -0700
committerSom Snytt <som.snytt@gmail.com>2015-06-21 10:29:04 -0700
commit3bfafbcf5903fc5c43190f1738c50bbbe0ca7d2b (patch)
tree41a0c371a8dc3de469f4c021b618f03610dcc524 /src
parenta9053f429983cc322a2fd2eca8fd0188036c7378 (diff)
downloadscala-3bfafbcf5903fc5c43190f1738c50bbbe0ca7d2b.tar.gz
scala-3bfafbcf5903fc5c43190f1738c50bbbe0ca7d2b.tar.bz2
scala-3bfafbcf5903fc5c43190f1738c50bbbe0ca7d2b.zip
SI-9206 Accept paste with custom prompt
But sans test.
Diffstat (limited to 'src')
-rw-r--r--src/partest-extras/scala/tools/partest/ReplTest.scala12
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ILoop.scala20
-rw-r--r--src/repl/scala/tools/nsc/interpreter/Pasted.scala20
3 files changed, 28 insertions, 24 deletions
diff --git a/src/partest-extras/scala/tools/partest/ReplTest.scala b/src/partest-extras/scala/tools/partest/ReplTest.scala
index 5b65d6ab9b..1fde2370d3 100644
--- a/src/partest-extras/scala/tools/partest/ReplTest.scala
+++ b/src/partest-extras/scala/tools/partest/ReplTest.scala
@@ -75,18 +75,20 @@ abstract class SessionTest extends ReplTest {
* Retain user input: prompt lines and continuations, without the prefix; or pasted text plus ctl-D.
*/
import SessionTest._
- override final def code = input findAllMatchIn (expected mkString ("", "\n", "\n")) map {
- case input(null, null, prompted) =>
+ lazy val pasted = input(prompt)
+ override final def code = pasted findAllMatchIn (expected mkString ("", "\n", "\n")) map {
+ case pasted(null, null, prompted) =>
def continued(m: Match): Option[String] = m match {
case margin(text) => Some(text)
case _ => None
}
margin.replaceSomeIn(prompted, continued)
- case input(cmd, pasted, null) =>
+ case pasted(cmd, pasted, null) =>
cmd + pasted + "\u0004"
} mkString
- final def prompt = "scala> "
+ // Just the last line of the interactive prompt
+ def prompt = "scala> "
/** Default test is to compare expected and actual output and emit the diff on a failed comparison. */
override def show() = {
@@ -98,7 +100,7 @@ abstract class SessionTest extends ReplTest {
}
object SessionTest {
// \R for line break is Java 8, \v for vertical space might suffice
- val input = """(?m)^scala> (:pa.*\u000A)// Entering paste mode.*\u000A\u000A((?:.*\u000A)*)\u000A// Exiting paste mode.*\u000A|^scala> (.*\u000A(?:\s*\| .*\u000A)*)""".r
+ 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
val margin = """(?m)^\s*\| (.*)$""".r
}
diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
index 89061730f6..992cafb9c6 100644
--- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
@@ -765,16 +765,13 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
}
private object paste extends Pasted {
+ import scala.util.matching.Regex.quote
val ContinueString = " | "
- val PromptString = "scala> "
- val testPrompt = PromptString.trim
- val testOurPrompt = prompt.trim
- val testBoth = testPrompt != testOurPrompt
+ val PromptString = prompt.lines.toList.last
+ val anyPrompt = s"""\\s*(?:${quote(PromptString.trim)}|${quote(AltPromptString.trim)})\\s*""".r
- def isPrompt(line: String) = {
- val text = line.trim
- text == testOurPrompt || (testBoth && text == testPrompt)
- }
+ 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)
@@ -784,10 +781,9 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
def transcript(start: String) = {
echo("\n// Detected repl transcript paste: ctrl-D to finish.\n")
- apply(Iterator(start) ++ readWhile(!isPrompt(_)))
+ apply(Iterator(start) ++ readWhile(!isPromptOnly(_)))
}
}
- import paste.{ ContinueString, PromptString }
/** Interpret expressions starting with the first line.
* Read lines until a complete compilation unit is available
@@ -809,7 +805,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
echo("You typed two blank lines. Starting a new command.")
None
}
- else in.readLine(ContinueString) match {
+ else in.readLine(paste.ContinueString) 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
@@ -833,7 +829,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
* and avoid the interpreter, as it's likely not valid scala code.
*/
if (code == "") None
- else if (!paste.running && code.trim.startsWith(PromptString)) {
+ else if (!paste.running && paste.isPrompted(code)) {
paste.transcript(code)
None
}
diff --git a/src/repl/scala/tools/nsc/interpreter/Pasted.scala b/src/repl/scala/tools/nsc/interpreter/Pasted.scala
index f5db3d9e3a..1600f32946 100644
--- a/src/repl/scala/tools/nsc/interpreter/Pasted.scala
+++ b/src/repl/scala/tools/nsc/interpreter/Pasted.scala
@@ -16,17 +16,21 @@ package interpreter
* the same result.
*/
abstract class Pasted {
+ def interpret(line: String): Unit
def ContinueString: String
def PromptString: String
- def interpret(line: String): Unit
+ def AltPromptString: String = "scala> "
+
+ private val testBoth = PromptString != AltPromptString
+ private val spacey = " \t".toSet
- def matchesPrompt(line: String) = matchesString(line, PromptString)
+ def matchesPrompt(line: String) = matchesString(line, PromptString) || testBoth && matchesString(line, AltPromptString)
def matchesContinue(line: String) = matchesString(line, ContinueString)
def running = isRunning
private def matchesString(line: String, target: String): Boolean = (
(line startsWith target) ||
- (line.nonEmpty && " \t".toSet(line.head) && matchesString(line.tail, target))
+ (line.nonEmpty && spacey(line.head) && matchesString(line.tail, target))
)
private def stripString(line: String, target: String) = line indexOf target match {
case -1 => line
@@ -39,7 +43,9 @@ abstract class Pasted {
private class PasteAnalyzer(val lines: List[String]) {
val referenced = lines flatMap (resReference findAllIn _.trim.stripPrefix("res")) toSet
- val cmds = lines reduceLeft append split PromptString filterNot (_.trim == "") toList
+ val ActualPromptString = lines find matchesPrompt map (s =>
+ if (matchesString(s, PromptString)) PromptString else AltPromptString) getOrElse PromptString
+ val cmds = lines reduceLeft append split ActualPromptString filterNot (_.trim == "") toList
/** If it's a prompt or continuation line, strip the formatting bits and
* assemble the code. Otherwise ship it off to be analyzed for res references
@@ -67,10 +73,10 @@ abstract class Pasted {
*/
def fixResRefs(code: String, line: String) = line match {
case resCreation(resName) if referenced(resName) =>
- code.lastIndexOf(PromptString) match {
+ code.lastIndexOf(ActualPromptString) match {
case -1 => code
case idx =>
- val (str1, str2) = code splitAt (idx + PromptString.length)
+ val (str1, str2) = code splitAt (idx + ActualPromptString.length)
str2 match {
case resAssign(`resName`) => code
case _ => "%sval %s = { %s }".format(str1, resName, str2)
@@ -82,7 +88,7 @@ abstract class Pasted {
def run() {
println("// Replaying %d commands from transcript.\n" format cmds.size)
cmds foreach { cmd =>
- print(PromptString)
+ print(ActualPromptString)
interpret(cmd)
}
}