summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/jline.jar.desired.sha12
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala66
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ILoop.scala31
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/IMain.scala26
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala17
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/JLineReader.scala42
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/package.scala18
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/session/package.scala1
-rw-r--r--src/jline/project/build.properties4
-rw-r--r--src/jline/project/plugins/project/build.properties2
-rw-r--r--src/jline/src/main/java/scala/tools/jline/WindowsTerminal.java2
-rw-r--r--src/jline/src/main/java/scala/tools/jline/console/ConsoleReader.java10
13 files changed, 172 insertions, 51 deletions
diff --git a/lib/jline.jar.desired.sha1 b/lib/jline.jar.desired.sha1
index b20982df23..d672b233ac 100644
--- a/lib/jline.jar.desired.sha1
+++ b/lib/jline.jar.desired.sha1
@@ -1 +1 @@
-50e6e3fad054ce6d0a077e85b457817039ede3c8 ?jline.jar
+80aedc428de3beae3608772523a8d29ffcef0e5b ?jline.jar
diff --git a/src/compiler/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala b/src/compiler/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala
new file mode 100644
index 0000000000..d0d3349038
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala
@@ -0,0 +1,66 @@
+/* NSC -- new Scala compiler
+ * Copyright 2005-2011 LAMP/EPFL
+ * @author Paul Phillips
+ */
+
+package scala.tools.nsc
+package interpreter
+
+import scala.tools.jline.console.{ ConsoleReader, CursorBuffer }
+import scala.tools.jline.console.completer.CompletionHandler
+import Completion._
+
+trait ConsoleReaderHelper extends ConsoleReader {
+ def currentLine = "" + getCursorBuffer.buffer
+ def currentPos = getCursorBuffer.cursor
+ def terminal = getTerminal()
+ def width = terminal.getWidth()
+ def height = terminal.getHeight()
+ def paginate = isPaginationEnabled()
+ def paginate_=(value: Boolean) = setPaginationEnabled(value)
+
+ def goBack(num: Int): Unit
+ def readOneKey(prompt: String): Int
+ def eraseLine(): Unit
+
+ private val marginSize = 3
+ private def morePrompt = "--More--"
+ private def emulateMore(): Int = {
+ val key = readOneKey(morePrompt)
+ try key match {
+ case '\r' | '\n' => 1
+ case 'q' => -1
+ case _ => height - 1
+ }
+ finally {
+ eraseLine()
+ // TODO: still not quite managing to erase --More-- and get
+ // back to a scala prompt without another keypress.
+ if (key == 'q') {
+ putString(getPrompt())
+ redrawLine()
+ flush()
+ }
+ }
+ }
+
+ override def printColumns(items: JCollection[_ <: CharSequence]): Unit =
+ printColumns(items: List[String])
+
+ def printColumns(items: List[String]): Unit = {
+ val longest = items map (_.length) max
+ var linesLeft = if (isPaginationEnabled()) height - 1 else Int.MaxValue
+ val columnSize = longest + marginSize
+ val padded = items map ("%-" + columnSize + "s" format _)
+
+ padded grouped (width / columnSize) foreach { xs =>
+ println(xs.mkString)
+ linesLeft -= 1
+ if (linesLeft <= 0) {
+ linesLeft = emulateMore()
+ if (linesLeft < 0)
+ return
+ }
+ }
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
index 90346c480f..38084af016 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
@@ -249,13 +249,6 @@ class ILoop(in0: Option[BufferedReader], protected val out: PrintWriter)
import global.Symbol
def p(x: Any) = intp.reporter.printMessage("" + x)
- def toDefString(sym: Symbol) = {
- TypeStrings.quieter(
- intp.afterTyper(sym.defString),
- sym.owner.name + ".this.",
- sym.owner.fullName + "."
- )
- }
// If an argument is given, only show a source with that
// in its name somewhere.
@@ -300,7 +293,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: PrintWriter)
p(" /* " + members.size + ownerMessage + owner.fullName + " */")
memberGroups foreach { group =>
- group foreach (s => p(" " + toDefString(s)))
+ group foreach (s => p(" " + intp.symbolDefString(s)))
p("")
}
}
@@ -392,6 +385,12 @@ class ILoop(in0: Option[BufferedReader], protected val out: PrintWriter)
else powerCommands
)
+ val replayQuestionMessage =
+ """|The repl compiler has crashed spectacularly. Shall I replay your
+ |session? I can re-run all lines except the last one.
+ |[y/n]
+ """.trim.stripMargin
+
private val crashRecovery: PartialFunction[Throwable, Unit] = {
case ex: Throwable =>
if (settings.YrichExes.value) {
@@ -406,9 +405,19 @@ class ILoop(in0: Option[BufferedReader], protected val out: PrintWriter)
else {
out.println(util.stackTraceString(ex))
}
- out.println("Attempting session recovery...")
-
- replay()
+ ex match {
+ case _: NoSuchMethodError | _: NoClassDefFoundError =>
+ out.println("Unrecoverable error.")
+ throw ex
+ case _ =>
+ out.print(replayQuestionMessage)
+ out.flush()
+ if (in.readAssumingNo("")) {
+ out.println("\nAttempting session recovery with replay.")
+ replay()
+ }
+ else out.println("\nAbandoning crashed session.")
+ }
}
/** The main read-eval-print loop for the repl. It calls
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
index c3cc0f9e03..33dcfa59e6 100644
--- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
@@ -83,6 +83,7 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
/** reporter */
lazy val reporter: ConsoleReporter = new IMain.ReplReporter(this)
import reporter.{ printMessage, withoutTruncating }
+
// not sure if we have some motivation to print directly to console
private def echo(msg: String) { Console println msg }
@@ -1088,6 +1089,14 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
finally isettings.unwrapStrings = saved
}
+ def symbolDefString(sym: Symbol) = {
+ TypeStrings.quieter(
+ afterTyper(sym.defString),
+ sym.owner.name + ".this.",
+ sym.owner.fullName + "."
+ )
+ }
+
def showCodeIfDebugging(code: String) {
/** Secret bookcase entrance for repl debuggers: end the line
* with "// show" and see what's going on.
@@ -1110,6 +1119,14 @@ class IMain(val settings: Settings, protected val out: PrintWriter) {
/** Utility methods for the Interpreter. */
object IMain {
+ // The two name forms this is catching are the two sides of this assignment:
+ //
+ // $line3.$read.$iw.$iw.Bippy =
+ // $line3.$read$$iw$$iw$Bippy@4a6a00ca
+ private def removeLineWrapper(s: String) = s.replaceAll("""\$line\d+[./]\$(read|eval|print)[$.]""", "")
+ private def removeIWPackages(s: String) = s.replaceAll("""\$(iw|read|eval|print)[$.]""", "")
+ def stripString(s: String) = removeIWPackages(removeLineWrapper(s))
+
trait CodeAssembler[T] {
def preamble: String
def generate: T => String
@@ -1152,7 +1169,7 @@ object IMain {
def isTruncating = reporter.truncationOK
def stripImpl(str: String): String = {
- val cleaned = removeIWPackages(removeLineWrapper(str))
+ val cleaned = stripString(str)
var ctrlChars = 0
cleaned map { ch =>
if (ch.isControl && !ch.isWhitespace) {
@@ -1163,13 +1180,6 @@ object IMain {
else ch
}
}
-
- // The two name forms this is catching are the two sides of this assignment:
- //
- // $line3.$read.$iw.$iw.Bippy =
- // $line3.$read$$iw$$iw$Bippy@4a6a00ca
- private def removeLineWrapper(s: String) = s.replaceAll("""\$line\d+[./]\$(read|eval|print)[$.]""", "")
- private def removeIWPackages(s: String) = s.replaceAll("""\$(iw|read|eval|print)[$.]""", "")
}
class ReplReporter(intp: IMain) extends ConsoleReporter(intp.settings, null, new ReplStrippingWriter(intp)) {
diff --git a/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala b/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
index 782fd52ab2..1430cbe55c 100644
--- a/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/InteractiveReader.scala
@@ -17,16 +17,25 @@ import Properties.isMac
trait InteractiveReader {
val interactive: Boolean
+ def init(): Unit
+ def reset(): Unit
+
def history: History
def completion: Completion
def keyBindings: List[KeyBinding]
+ def eraseLine(): Unit
+ def redrawLine(): Unit
+ def currentLine: String
- def init(): Unit
- def reset(): Unit
+ def readYesOrNo(prompt: String) = readOneKey(prompt) match {
+ case 'y' => true
+ case 'n' => false
+ }
+ def readAssumingNo(prompt: String) = try readYesOrNo(prompt) catch { case _: MatchError => false }
+ def readAssumingYes(prompt: String) = try readYesOrNo(prompt) catch { case _: MatchError => true }
protected def readOneLine(prompt: String): String
- def redrawLine(): Unit
- def currentLine: String
+ protected def readOneKey(prompt: String): Int
def readLine(prompt: String): String =
// hack necessary for OSX jvm suspension because read calls are not restarted after SIGTSTP
diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala b/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
index 9ca10b9e6b..d9260427b3 100644
--- a/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
@@ -35,33 +35,41 @@ class JLineReader(val completion: Completion) extends InteractiveReader {
}
}
- def argCompletor: ArgumentCompleter = {
- val c = new ArgumentCompleter(new JLineDelimiter, scalaToJline(completion.completer()))
- c setStrict false
- c
- }
+ class JLineConsoleReader extends ConsoleReader with ConsoleReaderHelper {
+ // working around protected/trait/java insufficiencies.
+ def goBack(num: Int): Unit = back(num)
+ def readOneKey(prompt: String) = {
+ this.print(prompt)
+ this.flush()
+ this.readVirtualKey()
+ }
+ def eraseLine() = consoleReader.resetPromptLine("", "", 0)
+ def redrawLineAndFlush(): Unit = { flush() ; drawLine() ; flush() }
- val consoleReader = {
- val r = new ConsoleReader()
- r setBellEnabled false
+ this setBellEnabled false
if (history ne NoHistory)
- r setHistory history
+ this setHistory history
if (completion ne NoCompletion) {
- r addCompleter argCompletor
- r setAutoprintThreshold 400 // max completion candidates without warning
- }
+ val argCompletor: ArgumentCompleter =
+ new ArgumentCompleter(new JLineDelimiter, scalaToJline(completion.completer()))
+ argCompletor setStrict false
- r
+ this addCompleter argCompletor
+ this setAutoprintThreshold 400 // max completion candidates without warning
+ }
}
+ val consoleReader: JLineConsoleReader = new JLineConsoleReader()
+
def currentLine: String = consoleReader.getCursorBuffer.buffer.toString
- def redrawLine() = {
- consoleReader.flush()
- consoleReader.drawLine()
- consoleReader.flush()
+ def redrawLine() = consoleReader.redrawLineAndFlush()
+ def eraseLine() = {
+ while (consoleReader.delete()) { }
+ // consoleReader.eraseLine()
}
def readOneLine(prompt: String) = consoleReader readLine prompt
+ def readOneKey(prompt: String) = consoleReader readOneKey prompt
}
object JLineReader {
diff --git a/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala b/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala
index d8181e1793..5249f89dfb 100644
--- a/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/SimpleReader.scala
@@ -22,6 +22,7 @@ extends InteractiveReader
def init() = ()
def reset() = ()
+ def eraseLine() = ()
def redrawLine() = ()
def currentLine = ""
def readOneLine(prompt: String): String = {
@@ -31,6 +32,7 @@ extends InteractiveReader
}
in.readLine()
}
+ def readOneKey(prompt: String) = sys.error("No char-based input in SimpleReader")
}
object SimpleReader {
diff --git a/src/compiler/scala/tools/nsc/interpreter/package.scala b/src/compiler/scala/tools/nsc/interpreter/package.scala
index 42826e9c6d..e2e6cb6651 100644
--- a/src/compiler/scala/tools/nsc/interpreter/package.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/package.scala
@@ -23,7 +23,9 @@ package scala.tools.nsc
* IMain contains { global: Global }
*/
package object interpreter {
- type JClass = java.lang.Class[_]
+ type JClass = java.lang.Class[_]
+ type JList[T] = java.util.List[T]
+ type JCollection[T] = java.util.Collection[T]
private[nsc] val DebugProperty = "scala.repl.debug"
private[nsc] val TraceProperty = "scala.repl.trace"
@@ -31,6 +33,10 @@ package object interpreter {
private[nsc] var isReplDebug = sys.props contains DebugProperty // Also set by -Yrepl-debug
private[nsc] implicit def enrichClass[T](clazz: Class[T]) = new RichClass[T](clazz)
+ private[interpreter] implicit def javaCharSeqCollectionToScala(xs: JCollection[_ <: CharSequence]): List[String] = {
+ import collection.JavaConverters._
+ xs.asScala.toList map ("" + _)
+ }
/** Debug output */
private[nsc] def repldbg(msg: String) = if (isReplDebug) Console println msg
@@ -43,6 +49,16 @@ package object interpreter {
x
}
+ // Longest common prefix
+ def longestCommonPrefix(xs: List[String]): String = {
+ if (xs.isEmpty || xs.contains("")) ""
+ else xs.head.head match {
+ case ch =>
+ if (xs.tail forall (_.head == ch)) "" + ch + longestCommonPrefix(xs map (_.tail))
+ else ""
+ }
+ }
+
private[nsc] def words(s: String) = s.trim split "\\s+" toList
private[nsc] def isQuoted(s: String) =
(s.length >= 2) && (s.head == s.last) && ("\"'" contains s.head)
diff --git a/src/compiler/scala/tools/nsc/interpreter/session/package.scala b/src/compiler/scala/tools/nsc/interpreter/session/package.scala
index e6ff2c3e03..8fbba2f05e 100644
--- a/src/compiler/scala/tools/nsc/interpreter/session/package.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/session/package.scala
@@ -12,7 +12,6 @@ package interpreter
package object session {
type JIterator[T] = java.util.Iterator[T]
type JListIterator[T] = java.util.ListIterator[T]
- type JList[T] = java.util.List[T]
type JEntry = scala.tools.jline.console.history.History.Entry
type JHistory = scala.tools.jline.console.history.History
diff --git a/src/jline/project/build.properties b/src/jline/project/build.properties
index c6143fe8df..3ecffcd808 100644
--- a/src/jline/project/build.properties
+++ b/src/jline/project/build.properties
@@ -3,6 +3,6 @@ project.organization=org.improving
project.name=jline
sbt.version=0.7.5.RC0
project.version=0.98
-#build.scala.versions=2.8.1
-build.scala.versions=2.9.0-SNAPSHOT
+build.scala.versions=2.8.1
+/*build.scala.versions=2.9.0-SNAPSHOT*/
project.initialize=false
diff --git a/src/jline/project/plugins/project/build.properties b/src/jline/project/plugins/project/build.properties
index f39984bd73..0b7014c531 100644
--- a/src/jline/project/plugins/project/build.properties
+++ b/src/jline/project/plugins/project/build.properties
@@ -1,3 +1,3 @@
#Project properties
-#Fri Jan 21 08:49:59 PST 2011
+#Thu Feb 10 14:58:03 PST 2011
plugin.uptodate=true
diff --git a/src/jline/src/main/java/scala/tools/jline/WindowsTerminal.java b/src/jline/src/main/java/scala/tools/jline/WindowsTerminal.java
index 66d2c69f8d..4c70155f59 100644
--- a/src/jline/src/main/java/scala/tools/jline/WindowsTerminal.java
+++ b/src/jline/src/main/java/scala/tools/jline/WindowsTerminal.java
@@ -196,6 +196,8 @@ public class WindowsTerminal
if (indicator == SPECIAL_KEY_INDICATOR.code || indicator == NUMPAD_KEY_INDICATOR.code) {
int c = readCharacter(in);
WindowsKey key = WindowsKey.valueOf(c);
+ if (key == null)
+ return 0;
switch (key) {
case UP_ARROW_KEY:
diff --git a/src/jline/src/main/java/scala/tools/jline/console/ConsoleReader.java b/src/jline/src/main/java/scala/tools/jline/console/ConsoleReader.java
index bff0a10648..861c2d58bd 100644
--- a/src/jline/src/main/java/scala/tools/jline/console/ConsoleReader.java
+++ b/src/jline/src/main/java/scala/tools/jline/console/ConsoleReader.java
@@ -219,7 +219,7 @@ public class ConsoleReader
*
* @return false if we failed (e.g., the buffer was empty)
*/
- final boolean resetLine() throws IOException {
+ protected final boolean resetLine() throws IOException {
if (buf.cursor == 0) {
return false;
}
@@ -378,7 +378,7 @@ public class ConsoleReader
* @param str
* @return
*/
- final String expandEvents(String str) throws IOException {
+ protected String expandEvents(String str) throws IOException {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < str.length(); i++) {
char c = str.charAt(i);
@@ -650,7 +650,7 @@ public class ConsoleReader
/**
* Move the visual cursor backwards without modifying the buffer cursor.
*/
- private void back(final int num) throws IOException {
+ protected void back(final int num) throws IOException {
if (num == 0) return;
if (terminal.isAnsiSupported()) {
int width = getTerminal().getWidth();
@@ -736,7 +736,7 @@ public class ConsoleReader
return backspace(1) == 1;
}
- private boolean moveToEnd() throws IOException {
+ protected boolean moveToEnd() throws IOException {
return moveCursor(buf.length() - buf.cursor) > 0;
}
@@ -1502,7 +1502,7 @@ public class ConsoleReader
*
* @return true if successful
*/
- private boolean complete() throws IOException {
+ protected boolean complete() throws IOException {
// debug ("tab for (" + buf + ")");
if (completers.size() == 0) {
return false;