summaryrefslogtreecommitdiff
path: root/src/repl
diff options
context:
space:
mode:
authorSom Snytt <som.snytt@gmail.com>2014-09-15 23:32:09 -0700
committerSom Snytt <som.snytt@gmail.com>2014-09-22 00:00:15 -0700
commite720babdaf999878642c18cebec4c18e93988d54 (patch)
tree050e8c543d2326bd129704450bbff0aba885682d /src/repl
parent252901054e40276abdb734673e41c6ce01adb7cc (diff)
downloadscala-e720babdaf999878642c18cebec4c18e93988d54.tar.gz
scala-e720babdaf999878642c18cebec4c18e93988d54.tar.bz2
scala-e720babdaf999878642c18cebec4c18e93988d54.zip
SI-6502 Repl reset/replay take settings args
The reset and replay commands take arbitrary command line args. When settings args are supplied, the compiler is recreated. For uniformity, the settings command performs only the usual arg parsing: use -flag:true instead of +flag, and clearing a setting is promoted to the command line, so that -Xlint: is not an error but clears the flags. ``` scala> maqicode.Test main null <console>:8: error: not found: value maqicode maqicode.Test main null ^ scala> :reset -classpath/a target/scala-2.11/sample_2.11-1.0.jar Resetting interpreter state. Forgetting all expression results and named terms: $intp scala> maqicode.Test main null Hello, world. scala> val i = 42 i: Int = 42 scala> s"$i is the loneliest numbah." res1: String = 42 is the loneliest numbah. scala> :replay -classpath "" Replaying: maqicode.Test main null Hello, world. Replaying: val i = 42 i: Int = 42 Replaying: s"$i is the loneliest numbah." res1: String = 42 is the loneliest numbah. scala> :replay -classpath/a "" Replaying: maqicode.Test main null <console>:8: error: not found: value maqicode maqicode.Test main null ^ Replaying: val i = 42 i: Int = 42 Replaying: s"$i is the loneliest numbah." res1: String = 42 is the loneliest numbah. ``` Clearing a clearable setting: ``` scala> :reset -Xlint:missing-interpolator Resetting interpreter state. scala> { val i = 42 ; "$i is the loneliest numbah." } <console>:8: warning: possible missing interpolator: detected interpolated identifier `$i` { val i = 42 ; "$i is the loneliest numbah." } ^ res0: String = $i is the loneliest numbah. scala> :reset -Xlint: Resetting interpreter state. Forgetting this session history: { val i = 42 ; "$i is the loneliest numbah." } scala> { val i = 42 ; "$i is the loneliest numbah." } res0: String = $i is the loneliest numbah. ```
Diffstat (limited to 'src/repl')
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ILoop.scala101
-rw-r--r--src/repl/scala/tools/nsc/interpreter/ReplStrings.scala5
2 files changed, 44 insertions, 62 deletions
diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
index 9353d03a08..6a3528d1c9 100644
--- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala
@@ -220,12 +220,12 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
cmd("paste", "[-raw] [path]", "enter paste mode or paste a file", pasteCommand),
nullary("power", "enable power user mode", powerCmd),
nullary("quit", "exit the interpreter", () => Result(keepRunning = false, None)),
- nullary("replay", "reset execution and replay all previous commands", replay),
+ cmd("replay", "[options]", "reset the repl and replay all previous commands", replayCommand),
//cmd("require", "<path>", "add a jar or directory to the classpath", require), // TODO
- nullary("reset", "reset the repl to its initial state, forgetting all session entries", resetCommand),
+ cmd("reset", "[options]", "reset the repl to its initial state, forgetting all session entries", resetCommand),
cmd("save", "<path>", "save replayable session to a file", saveCommand),
shCommand,
- cmd("settings", "[+|-]<options>", "+enable/-disable flags, set compiler options", changeSettings),
+ cmd("settings", "<options>", "update compiler options, if possible; see reset", changeSettings),
nullary("silent", "disable/enable automatic printing of results", verbosity),
cmd("type", "[-v] <expr>", "display the type of an expression without evaluating it", typeCommand),
cmd("kind", "[-v] <expr>", "display the kind of expression's type", kindCommand),
@@ -305,57 +305,23 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
intp.lastWarnings foreach { case (pos, msg) => intp.reporter.warning(pos, msg) }
}
- private def changeSettings(args: String): Result = {
- def showSettings() = {
- for (s <- settings.userSetSettings.toSeq.sorted) echo(s.toString)
- }
- def updateSettings() = {
- // put aside +flag options
- val (pluses, rest) = (args split "\\s+").toList partition (_.startsWith("+"))
- val tmps = new Settings
- val (ok, leftover) = tmps.processArguments(rest, processAll = true)
- if (!ok) echo("Bad settings request.")
- else if (leftover.nonEmpty) echo("Unprocessed settings.")
- else {
- // boolean flags set-by-user on tmp copy should be off, not on
- val offs = tmps.userSetSettings filter (_.isInstanceOf[Settings#BooleanSetting])
- val (minuses, nonbools) = rest partition (arg => offs exists (_ respondsTo arg))
- // update non-flags
- settings.processArguments(nonbools, processAll = true)
- // also snag multi-value options for clearing, e.g. -Ylog: and -language:
- for {
- s <- settings.userSetSettings
- if s.isInstanceOf[Settings#MultiStringSetting] || s.isInstanceOf[Settings#PhasesSetting]
- if nonbools exists (arg => arg.head == '-' && arg.last == ':' && (s respondsTo arg.init))
- } s match {
- case c: Clearable => c.clear()
- case _ =>
- }
- def update(bs: Seq[String], name: String=>String, setter: Settings#Setting=>Unit) = {
- for (b <- bs)
- settings.lookupSetting(name(b)) match {
- case Some(s) =>
- if (s.isInstanceOf[Settings#BooleanSetting]) setter(s)
- else echo(s"Not a boolean flag: $b")
- case _ =>
- echo(s"Not an option: $b")
- }
- }
- update(minuses, identity, _.tryToSetFromPropertyValue("false")) // turn off
- update(pluses, "-" + _.drop(1), _.tryToSet(Nil)) // turn on
- }
- }
- if (args.isEmpty) showSettings() else updateSettings()
+ private def changeSettings(line: String): Result = {
+ def showSettings() = for (s <- settings.userSetSettings.toSeq.sorted) echo(s.toString)
+ if (line.isEmpty) showSettings() else { updateSettings(line) ; () }
+ }
+ private def updateSettings(line: String) = {
+ val (ok, rest) = settings.processArguments(words(line), processAll = false)
+ ok && rest.isEmpty
}
private def javapCommand(line: String): Result = {
if (javap == null)
- ":javap unavailable, no tools.jar at %s. Set JDK_HOME.".format(jdkHome)
+ s":javap unavailable, no tools.jar at $jdkHome. Set JDK_HOME."
else if (line == "")
":javap [-lcsvp] [path1 path2 ...]"
else
javap(words(line)) foreach { res =>
- if (res.isError) return "Failed: " + res.value
+ if (res.isError) return s"Failed: ${res.value}"
else res.show()
}
}
@@ -473,8 +439,16 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
}
/** create a new interpreter and replay the given commands */
- def replay() {
- reset()
+ def replayCommand(line: String): Unit = {
+ def run(destructive: Boolean): Unit = {
+ if (destructive) createInterpreter() else reset()
+ replay()
+ }
+ if (line.isEmpty) run(destructive = false)
+ else if (updateSettings(line)) run(destructive = true)
+ }
+ /** Announces as it replays. */
+ def replay(): Unit = {
if (replayCommandStack.isEmpty)
echo("Nothing to replay.")
else for (cmd <- replayCommands) {
@@ -484,22 +458,27 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
}
}
/** `reset` the interpreter in an attempt to start fresh.
+ * Supplying settings creates a new compiler.
*/
- def resetCommand() {
- echo("Resetting interpreter state.")
- if (replayCommandStack.nonEmpty) {
- echo("Forgetting this session history:\n")
- replayCommands foreach echo
- echo("")
- replayCommandStack = Nil
+ def resetCommand(line: String): Unit = {
+ def run(destructive: Boolean): Unit = {
+ echo("Resetting interpreter state.")
+ if (replayCommandStack.nonEmpty) {
+ echo("Forgetting this session history:\n")
+ replayCommands foreach echo
+ echo("")
+ replayCommandStack = Nil
+ }
+ if (intp.namedDefinedTerms.nonEmpty)
+ echo("Forgetting all expression results and named terms: " + intp.namedDefinedTerms.mkString(", "))
+ if (intp.definedTypes.nonEmpty)
+ echo("Forgetting defined types: " + intp.definedTypes.mkString(", "))
+ if (destructive) createInterpreter() else reset()
}
- if (intp.namedDefinedTerms.nonEmpty)
- echo("Forgetting all expression results and named terms: " + intp.namedDefinedTerms.mkString(", "))
- if (intp.definedTypes.nonEmpty)
- echo("Forgetting defined types: " + intp.definedTypes.mkString(", "))
-
- reset()
+ if (line.isEmpty) run(destructive = false)
+ else if (updateSettings(line)) run(destructive = true)
}
+ /** Resets without announcements. */
def reset() {
intp.reset()
unleashAndSetPhase()
diff --git a/src/repl/scala/tools/nsc/interpreter/ReplStrings.scala b/src/repl/scala/tools/nsc/interpreter/ReplStrings.scala
index 43da5c6f12..1664546cab 100644
--- a/src/repl/scala/tools/nsc/interpreter/ReplStrings.scala
+++ b/src/repl/scala/tools/nsc/interpreter/ReplStrings.scala
@@ -28,5 +28,8 @@ trait ReplStrings {
def any2stringOf(x: Any, maxlen: Int) =
"scala.runtime.ScalaRunTime.replStringOf(%s, %s)".format(x, maxlen)
- def words(s: String) = (s.trim split "\\s+" filterNot (_ == "")).toList
+ // no escaped or nested quotes
+ private[this] val inquotes = """(['"])(.*?)\1""".r
+ def unquoted(s: String) = s match { case inquotes(_, w) => w ; case _ => s }
+ def words(s: String) = (s.trim split "\\s+" filterNot (_ == "") map unquoted).toList
}