summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/nsc/Interpreter.scala5
-rw-r--r--src/compiler/scala/tools/nsc/InterpreterLoop.scala75
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Completion.scala39
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/JLineReader.scala18
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala2
6 files changed, 107 insertions, 36 deletions
diff --git a/src/compiler/scala/tools/nsc/Interpreter.scala b/src/compiler/scala/tools/nsc/Interpreter.scala
index 55e3b354e5..06a364e4a4 100644
--- a/src/compiler/scala/tools/nsc/Interpreter.scala
+++ b/src/compiler/scala/tools/nsc/Interpreter.scala
@@ -484,6 +484,9 @@ class Interpreter(val settings: Settings, out: PrintWriter)
interpret("val %s = %s.value".format(name, binderName))
}
+ def quietBind(name: String, boundType: String, value: Any): IR.Result =
+ beQuietDuring { bind(name, boundType, value) }
+
/** Reset this interpreter, forgetting all user-specified requests. */
def reset() {
virtualDirectory.clear
@@ -789,7 +792,7 @@ class Interpreter(val settings: Settings, out: PrintWriter)
List(classOf[InvocationTargetException], classOf[ExceptionInInitializerError])
def onErr: Catcher[(String, Boolean)] = { case t: Throwable =>
- beQuietDuring { bind("lastException", "java.lang.Throwable", t) }
+ quietBind("lastException", "java.lang.Throwable", t)
(stringFrom(t.printStackTrace(_)), false)
}
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)
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Completion.scala b/src/compiler/scala/tools/nsc/interpreter/Completion.scala
index 2ecafa974a..2b9538b3fc 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Completion.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Completion.scala
@@ -31,7 +31,12 @@ import scala.util.NameTransformer.{ decode, encode }
// REPL completor - queries supplied interpreter for valid completions
// based on current contents of buffer.
-class Completion(val interpreter: Interpreter) extends Completor {
+class Completion(
+ val interpreter: Interpreter,
+ val intLoop: InterpreterLoop)
+extends Completor {
+ def this(interpreter: Interpreter) = this(interpreter, null)
+
import Completion._
import java.util.{ List => JList }
import interpreter.compilerClasspath
@@ -59,7 +64,7 @@ class Completion(val interpreter: Interpreter) extends Completor {
}
// One instance of a command line
- class Buffer(s: String) {
+ class Buffer(s: String, verbose: Boolean) {
val buffer = if (s == null) "" else s
def isEmptyBuffer = buffer == ""
@@ -133,25 +138,29 @@ class Completion(val interpreter: Interpreter) extends Completor {
}
def membersOfPredef() = membersOfId("scala.Predef")
- def javaLangToHide(s: String) =
+ def javaLangToHide(s: String) = (
(s endsWith "Exception") ||
(s endsWith "Error") ||
(s endsWith "Impl") ||
(s startsWith "CharacterData") ||
!existsAndPublic("java.lang." + s)
+ )
def scalaToHide(s: String) =
(List("Tuple", "Product", "Function") exists (x => (x + """\d+""").r findPrefixMatchOf s isDefined)) ||
(List("Exception", "Error") exists (s endsWith _))
- def defaultMembers = (List("scala", "java.lang") flatMap membersOfPath) ::: membersOfPredef
+ /** Hide all default members not verbose */
+ def defaultMembers =
+ if (verbose) (List("scala", "java.lang") flatMap membersOfPath) ::: membersOfPredef
+ else Nil
def pkgsStartingWith(s: String) = topLevelPackages() filter (_ startsWith s)
def idsStartingWith(s: String) = {
- // on a totally empty buffer, filter out res*
+ // only print res* when verbose
val unqIds =
- if (s == "") interpreter.unqualifiedIds filterNot (_ startsWith INTERPRETER_VAR_PREFIX)
- else interpreter.unqualifiedIds
+ if (verbose) interpreter.unqualifiedIds
+ else interpreter.unqualifiedIds filterNot (_ startsWith INTERPRETER_VAR_PREFIX)
(unqIds ::: defaultMembers) filter (_ startsWith s)
}
@@ -175,9 +184,21 @@ class Completion(val interpreter: Interpreter) extends Completor {
(interpreter getClassObject ("scala." + path)) orElse
(interpreter getClassObject ("java.lang." + path))
+ def lastHistoryItem =
+ for (loop <- Option(intLoop) ; h <- loop.history) yield
+ h.getHistoryList.get(h.size - 1)
+
+ // Is the buffer the same it was last time they hit tab?
+ private var lastTab: (String, String) = (null, null)
+
// jline's completion comes through here - we ask a Buffer for the candidates.
- override def complete(_buffer: String, cursor: Int, candidates: JList[String]): Int =
- new Buffer(_buffer) complete candidates
+ override def complete(_buffer: String, cursor: Int, candidates: JList[String]): Int = {
+ // println("_buffer = %s, cursor = %d".format(_buffer, cursor))
+ val verbose = (_buffer, lastHistoryItem orNull) == lastTab
+ lastTab = (_buffer, lastHistoryItem orNull)
+
+ new Buffer(_buffer, verbose) complete candidates
+ }
def completePackageMembers(path: String): List[String] =
getClassObject(path + "." + "package") map (getMembers(_, false)) getOrElse Nil
diff --git a/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala b/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
index f2eb30cf14..500876bf69 100644
--- a/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
@@ -38,9 +38,9 @@ object InteractiveReader {
/** Create an interactive reader. Uses <code>JLineReader</code> if the
* library is available, but otherwise uses a <code>SimpleReader</code>.
*/
- def createDefault(interpreter: Interpreter): InteractiveReader =
+ def createDefault(interpreter: Interpreter, intLoop: InterpreterLoop = null): InteractiveReader =
catching(exes: _*)
- . opt (new JLineReader(interpreter))
+ . opt (new JLineReader(interpreter, intLoop))
. getOrElse (new SimpleReader)
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala b/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
index 59d6f0ac0a..b13b54a716 100644
--- a/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
@@ -11,15 +11,17 @@ import java.io.File
import jline.{ History, ConsoleReader, ArgumentCompletor }
/** Reads from the console using JLine */
-class JLineReader(interpreter: Interpreter) extends InteractiveReader {
- def this() = this(null)
+class JLineReader(interpreter: Interpreter, intLoop: InterpreterLoop) extends InteractiveReader {
+ def this() = this(null, null)
+ def this(interpreter: Interpreter) = this(interpreter, null)
+ def history: History = consoleReader.getHistory
+
val consoleReader = {
- val history = try {
- new jline.History(new File(System.getProperty("user.home"), ".scala_history"))
- } catch {
+ val history =
+ try new History(new File(System.getProperty("user.home"), ".scala_history"))
// do not store history if error
- case _ => new jline.History()
- }
+ catch { case _: Exception => new History() }
+
val r = new jline.ConsoleReader()
r setHistory history
r setBellEnabled false
@@ -30,7 +32,7 @@ class JLineReader(interpreter: Interpreter) extends InteractiveReader {
val delimChars = "(){}[],`;'\" \t".toArray
def isDelimiterChar(s: String, pos: Int) = delimChars contains s.charAt(pos)
}
- val comp = new ArgumentCompletor(new Completion(interpreter), delims)
+ val comp = new ArgumentCompletor(new Completion(interpreter, intLoop), delims)
comp setStrict false
r addCompletor comp
// XXX make this use a setting
diff --git a/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala b/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala
index 112b3e1e82..bca2e18e39 100644
--- a/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala
@@ -7,7 +7,7 @@
package scala.tools.nsc
package interpreter
-import java.io.{BufferedReader, PrintWriter}
+import java.io.{ BufferedReader, PrintWriter }
/** Reads using standard JDK API */
class SimpleReader(