summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/InterpreterLoop.scala
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/scala/tools/nsc/InterpreterLoop.scala')
-rw-r--r--src/compiler/scala/tools/nsc/InterpreterLoop.scala75
1 files changed, 60 insertions, 15 deletions
diff --git a/src/compiler/scala/tools/nsc/InterpreterLoop.scala b/src/compiler/scala/tools/nsc/InterpreterLoop.scala
index 76f09f07f7..2b926d8e80 100644
--- a/src/compiler/scala/tools/nsc/InterpreterLoop.scala
+++ b/src/compiler/scala/tools/nsc/InterpreterLoop.scala
@@ -10,6 +10,7 @@ import java.io.{ BufferedReader, File, FileReader, PrintWriter }
import java.io.IOException
import scala.tools.nsc.{ InterpreterResults => IR }
+import scala.collection.JavaConversions.asBuffer
import interpreter._
import io.{ Process }
@@ -22,30 +23,34 @@ object InterpreterControl {
// a single interpreter command
sealed abstract class Command extends Function1[List[String], Result] {
- val name: String
- val help: String
+ def name: String
+ def help: String
def error(msg: String) = {
println(":" + name + " " + msg + ".")
Result(true, None)
}
- def getHelp(): String = ":" + name + " " + help + "."
+ def usage(): String
}
case class NoArgs(name: String, help: String, f: () => Result) extends Command {
+ def usage(): String = ":" + name
def apply(args: List[String]) = if (args.isEmpty) f() else error("accepts no arguments")
}
case class LineArg(name: String, help: String, f: (String) => Result) extends Command {
+ def usage(): String = ":" + name + " <line>"
def apply(args: List[String]) = f(args mkString " ")
}
case class OneArg(name: String, help: String, f: (String) => Result) extends Command {
+ def usage(): String = ":" + name + " <arg>"
def apply(args: List[String]) =
if (args.size == 1) f(args.head)
else error("requires exactly one argument")
}
case class VarArgs(name: String, help: String, f: (List[String]) => Result) extends Command {
+ def usage(): String = ":" + name + " [arg]"
def apply(args: List[String]) = f(args)
}
@@ -54,8 +59,6 @@ object InterpreterControl {
}
import InterpreterControl._
-// import scala.concurrent.ops.defaultRunner
-
/** The
* <a href="http://scala-lang.org/" target="_top">Scala</a>
* interactive shell. It provides a read-eval-print loop around
@@ -76,6 +79,12 @@ class InterpreterLoop(in0: Option[BufferedReader], out: PrintWriter) {
/** The input stream from which commands come, set by main() */
var in: InteractiveReader = _
+ def history = in match {
+ case x: JLineReader => Some(x.history)
+ case _ => None
+ }
+ def historyList: Seq[String] =
+ history map (x => asBuffer(x.getHistoryList): Seq[String]) getOrElse Nil
/** The context class loader at the time this object was created */
protected val originalClassLoader = Thread.currentThread.getContextClassLoader
@@ -126,8 +135,11 @@ class InterpreterLoop(in0: Option[BufferedReader], out: PrintWriter) {
/** print a friendly help message */
def printHelp() = {
- out println "All commands can be abbreviated - for example :h or :he instead of :help.\n"
- commands foreach { c => out println c.getHelp }
+ out println "All commands can be abbreviated - for example :he instead of :help.\n"
+ val cmds = commands map (x => (x.usage, x.help))
+ val width: Int = cmds map { case (x, _) => x.length } max
+ val formatStr = "%-" + width + "s %s"
+ cmds foreach { case (usage, help) => out println formatStr.format(usage, help) }
}
/** Print a welcome message */
@@ -143,6 +155,36 @@ class InterpreterLoop(in0: Option[BufferedReader], out: PrintWriter) {
out.flush
}
+ /** Show the history */
+ def printHistory(xs: List[String]) {
+ val defaultLines = 20
+
+ if (history.isEmpty)
+ return println("No history available.")
+
+ val current = history.get.getCurrentIndex
+ val count = try xs.head.toInt catch { case _: Exception => defaultLines }
+ val lines = historyList takeRight count
+ val offset = current - lines.size + 1
+
+ for ((line, index) <- lines.zipWithIndex)
+ println("%d %s".format(index + offset, line))
+ }
+
+ /** Search the history */
+ def searchHistory(_cmdline: String) {
+ val cmdline = _cmdline.toLowerCase
+
+ if (history.isEmpty)
+ return println("No history available.")
+
+ val current = history.get.getCurrentIndex
+ val offset = current - historyList.size + 1
+
+ for ((line, index) <- historyList.zipWithIndex ; if line.toLowerCase contains cmdline)
+ println("%d %s".format(index + offset, line))
+ }
+
/** Prompt to print when awaiting input */
val prompt = Properties.shellPromptString
@@ -160,13 +202,15 @@ class InterpreterLoop(in0: Option[BufferedReader], out: PrintWriter) {
val standardCommands: List[Command] = {
import CommandImplicits._
List(
- NoArgs("help", "prints this help message", printHelp),
+ NoArgs("help", "print this help message", printHelp),
+ VarArgs("history", "show the history (optional arg: lines to show)", printHistory),
+ LineArg("h?", "search the history", searchHistory),
OneArg("jar", "add a jar to the classpath", addJar),
- OneArg("load", "followed by a filename loads a Scala file", load),
+ OneArg("load", "load and interpret a Scala file", load),
NoArgs("power", "enable power user mode", power),
- NoArgs("quit", "exits the interpreter", () => Result(false, None)),
- NoArgs("replay", "resets execution and replays all previous commands", replay),
- LineArg("sh", "forks a shell and runs a command", runShellCmd),
+ NoArgs("quit", "exit the interpreter", () => Result(false, None)),
+ NoArgs("replay", "reset execution and replay all previous commands", replay),
+ LineArg("sh", "fork a shell and run a command", runShellCmd),
NoArgs("silent", "disable/enable automatic printing of results", verbosity)
)
}
@@ -296,9 +340,10 @@ class InterpreterLoop(in0: Option[BufferedReader], out: PrintWriter) {
replay()
}
- def power() = {
+ def power() {
powerUserOn = true
interpreter.powerUser()
+ interpreter.quietBind("history", "scala.collection.immutable.List[String]", historyList.toList)
}
def verbosity() = {
@@ -381,7 +426,7 @@ class InterpreterLoop(in0: Option[BufferedReader], out: PrintWriter) {
// the interpeter is passed as an argument to expose tab completion info
if (settings.Xnojline.value || emacsShell) new SimpleReader
else if (settings.noCompletion.value) InteractiveReader.createDefault()
- else InteractiveReader.createDefault(interpreter)
+ else InteractiveReader.createDefault(interpreter, this)
}
loadFiles(settings)
@@ -399,7 +444,7 @@ class InterpreterLoop(in0: Option[BufferedReader], out: PrintWriter) {
// injects one value into the repl; returns pair of name and class
def injectOne(name: String, obj: Any): Tuple2[String, String] = {
val className = obj.asInstanceOf[AnyRef].getClass.getName
- interpreter.bind(name, className, obj)
+ interpreter.quietBind(name, className, obj)
(name, className)
}