summaryrefslogtreecommitdiff
path: root/src/compiler
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2010-12-12 19:13:10 +0000
committerPaul Phillips <paulp@improving.org>2010-12-12 19:13:10 +0000
commit5d6b870ea8b7b62670d616b055b85b03f061ba2b (patch)
treee419b0033657dfa3a49ce3513458a04f32c59816 /src/compiler
parent9c238c6accf43f2bfe9bcfcdc7aa2384e71dc165 (diff)
downloadscala-5d6b870ea8b7b62670d616b055b85b03f061ba2b.tar.gz
scala-5d6b870ea8b7b62670d616b055b85b03f061ba2b.tar.bz2
scala-5d6b870ea8b7b62670d616b055b85b03f061ba2b.zip
New jline: BSD licensed, based on [ https://git...
New jline: BSD licensed, based on [ https://github.com/jdillon/jline2 ] with additional code thanks to [ https://github.com/huynhjl/jline2 ]. Replaces lib/jline.jar with build of these sources, and modifies trunk code to work with the new jar. Hopeful improvements including baseline functionality on cygwin and 64bit windows, as well as more accurate line wrapping / cursor positioning on all platforms and ctrl-R history search. For the time being the canonical source repository is this: https://github.com/paulp/jline2 The enclosed sources are a mirror of that repository, and should be treated as read-only in the scala svn repository. No review, codewise, but people are very strongly encouraged to try it out and report any regressions.
Diffstat (limited to 'src/compiler')
-rw-r--r--src/compiler/scala/tools/ant/templates/tool-unix.tmpl23
-rw-r--r--src/compiler/scala/tools/nsc/InterpreterLoop.scala25
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Completion.scala12
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Delimited.scala6
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/History.scala30
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/JLineReader.scala29
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Parsed.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/package.scala7
-rw-r--r--src/compiler/scala/tools/nsc/settings/ScalaSettings.scala3
9 files changed, 91 insertions, 46 deletions
diff --git a/src/compiler/scala/tools/ant/templates/tool-unix.tmpl b/src/compiler/scala/tools/ant/templates/tool-unix.tmpl
index 2a42892739..0891ef8316 100644
--- a/src/compiler/scala/tools/ant/templates/tool-unix.tmpl
+++ b/src/compiler/scala/tools/ant/templates/tool-unix.tmpl
@@ -50,6 +50,10 @@ if [ -z "$TOOL_CLASSPATH" ] ; then
done
fi
+EXEC=exec
+CYGWIN_TERM_PRE=
+CYGWIN_TERM_POST=
+CYGWIN_JLINE_TERMINAL=
if $cygwin; then
if [ "$OS" = "Windows_NT" ] && cygpath -m .>/dev/null 2>/dev/null ; then
format=mixed
@@ -58,9 +62,19 @@ if $cygwin; then
fi
SCALA_HOME=`cygpath --$format "$SCALA_HOME"`
TOOL_CLASSPATH=`cygpath --path --$format "$TOOL_CLASSPATH"`
+ case "$TERM" in
+ rxvt* | xterm*)
+ EXEC=
+ CYGWIN_TERM_PRE="stty -icanon min 1 -echo"
+ CYGWIN_TERM_POST="stty icanon echo"
+ CYGWIN_JLINE_TERMINAL="-Djline.terminal=jline.UnixTerminal"
+ trap "$CYGWIN_TERM_POST" SIGINT
+ ;;
+ esac
+else
+ trap "stty echo" SIGINT
fi
-# Reminder: substitution ${JAVA_OPTS:=-Xmx256M -Xms16M} DO NOT work on Solaris
[ -n "$JAVA_OPTS" ] || JAVA_OPTS="@javaflags@"
# break out -D and -J options and add them to JAVA_OPTS as well
@@ -97,11 +111,16 @@ if [ -z "$JAVACMD" -a -n "$JAVA_HOME" -a -x "$JAVA_HOME/bin/java" ]; then
JAVACMD="$JAVA_HOME/bin/java"
fi
-exec "${JAVACMD:=java}" \
+eval $CYGWIN_TERM_PRE
+
+$EXEC "${JAVACMD:=java}" \
$JAVA_OPTS \
"${java_args[@@]}" \
$CPSWITCH \
-Dscala.usejavacp=true \
-Dscala.home="$SCALA_HOME" \
-Denv.emacs="$EMACS" \
+ $CYGWIN_JLINE_TERMINAL \
@properties@ @class@ @toolflags@ "$@@"
+
+eval $CYGWIN_TERM_POST
diff --git a/src/compiler/scala/tools/nsc/InterpreterLoop.scala b/src/compiler/scala/tools/nsc/InterpreterLoop.scala
index 6f2bcdb74a..ebfecc7204 100644
--- a/src/compiler/scala/tools/nsc/InterpreterLoop.scala
+++ b/src/compiler/scala/tools/nsc/InterpreterLoop.scala
@@ -195,17 +195,14 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
/** Show the history */
def printHistory(xs: List[String]) {
val defaultLines = 20
-
- if (in.history.isEmpty)
- return println("No history available.")
-
- val current = in.history.get.index
- val count = try xs.head.toInt catch { case _: Exception => defaultLines }
- val lines = in.historyList takeRight count
- val offset = current - lines.size + 1
+ val h = in.history getOrElse { return println("No history available.") }
+ val current = h.index
+ val count = try xs.head.toInt catch { case _: Exception => defaultLines }
+ val lines = in.historyList takeRight count
+ val offset = current - lines.size + 1
for ((line, index) <- lines.zipWithIndex)
- println("%d %s".format(index + offset, line))
+ println("%3d %s".format(index + offset, line.value))
}
/** Some print conveniences */
@@ -216,14 +213,10 @@ class InterpreterLoop(in0: Option[BufferedReader], protected val out: PrintWrite
/** Search the history */
def searchHistory(_cmdline: String) {
val cmdline = _cmdline.toLowerCase
+ val h = in.history getOrElse { return println("No history available.") }
+ val offset = h.index - h.size + 1
- if (in.history.isEmpty)
- return println("No history available.")
-
- val current = in.history.get.index
- val offset = current - in.historyList.size + 1
-
- for ((line, index) <- in.historyList.zipWithIndex ; if line.toLowerCase contains cmdline)
+ for ((line, index) <- h.asStrings.zipWithIndex ; if line.toLowerCase contains cmdline)
println("%d %s".format(index + offset, line))
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Completion.scala b/src/compiler/scala/tools/nsc/interpreter/Completion.scala
index 426f2debf4..971146ea14 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Completion.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Completion.scala
@@ -8,6 +8,7 @@ package scala.tools.nsc
package interpreter
import jline._
+import jline.console.completer._
import java.util.{ List => JList }
import util.returning
@@ -285,8 +286,11 @@ class Completion(val repl: Interpreter) extends CompletionOutput {
topLevelFor(Parsed.dotted(buf + ".", buf.length + 1))
// jline's entry point
- lazy val jline: ArgumentCompletor =
- returning(new ArgumentCompletor(new JLineCompletion, new JLineDelimiter))(_ setStrict false)
+ lazy val jline: ArgumentCompleter = {
+ val c = new ArgumentCompleter(new JLineDelimiter, new JLineCompletion)
+ c setStrict false
+ c
+ }
/** This gets a little bit hairy. It's no small feat delegating everything
* and also keeping track of exactly where the cursor is and where it's supposed
@@ -294,7 +298,7 @@ class Completion(val repl: Interpreter) extends CompletionOutput {
* string in the list of completions, that means we are expanding a unique
* completion, so don't update the "last" buffer because it'll be wrong.
*/
- class JLineCompletion extends Completor {
+ class JLineCompletion extends Completer {
// For recording the buffer on the last tab hit
private var lastBuf: String = ""
private var lastCursor: Int = -1
@@ -309,7 +313,7 @@ class Completion(val repl: Interpreter) extends CompletionOutput {
else xs.reduceLeft(_ zip _ takeWhile (x => x._1 == x._2) map (_._1) mkString)
// This is jline's entry point for completion.
- override def complete(_buf: String, cursor: Int, candidates: JList[String]): Int = {
+ override def complete(_buf: String, cursor: Int, candidates: JList[CharSequence]): Int = {
val buf = if (_buf == null) "" else _buf
verbosity = if (isConsecutiveTabs(buf, cursor)) verbosity + 1 else 0
DBG("\ncomplete(%s, %d) last = (%s, %d), verbosity: %s".format(buf, cursor, lastBuf, lastCursor, verbosity))
diff --git a/src/compiler/scala/tools/nsc/interpreter/Delimited.scala b/src/compiler/scala/tools/nsc/interpreter/Delimited.scala
index cdf5a343da..a79507baa9 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Delimited.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Delimited.scala
@@ -6,11 +6,11 @@
package scala.tools.nsc
package interpreter
-import jline.ArgumentCompletor.{ ArgumentDelimiter, ArgumentList }
+import jline.console.completer.ArgumentCompleter.{ ArgumentDelimiter, ArgumentList }
class JLineDelimiter extends ArgumentDelimiter {
- def delimit(buffer: String, cursor: Int) = Parsed(buffer, cursor).asJlineArgumentList
- def isDelimiter(buffer: String, cursor: Int) = Parsed(buffer, cursor).isDelimiter
+ def delimit(buffer: CharSequence, cursor: Int) = Parsed(buffer.toString, cursor).asJlineArgumentList
+ def isDelimiter(buffer: CharSequence, cursor: Int) = Parsed(buffer.toString, cursor).isDelimiter
}
trait Delimited {
diff --git a/src/compiler/scala/tools/nsc/interpreter/History.scala b/src/compiler/scala/tools/nsc/interpreter/History.scala
index 1dd85cda4d..4750b8ec60 100644
--- a/src/compiler/scala/tools/nsc/interpreter/History.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/History.scala
@@ -7,18 +7,27 @@ package scala.tools.nsc
package interpreter
import java.io.File
-import jline.{ ConsoleReader, History => JHistory }
-import scala.collection.JavaConversions.asScalaBuffer
+import jline.console.history._
+import jline.console.history.{ FileHistory, PersistentHistory, History => JHistory }
+import jline.console.history.History.{ Entry => JEntry }
+import jline.console.ConsoleReader
+import scala.collection.JavaConverters._
import Properties.userHome
/** Primarily, a wrapper for JLine's History.
*/
class History(val jhistory: JHistory) {
- def asJavaList = jhistory.getHistoryList
- def asList: List[String] = asScalaBuffer(asJavaList).toList
- def index = jhistory.getCurrentIndex
+ def asJavaList = jhistory.entries()
+ def asStrings = asList map (_.value.toString)
+ def asList: List[JEntry] = asJavaList.asScala.toList
+ def index = jhistory.index()
+ def size = jhistory.size()
- def grep(s: String) = asList filter (_ contains s)
+ def grep(s: String) = asStrings filter (_ contains s)
+ def flush() = jhistory match {
+ case x: PersistentHistory => x.flush()
+ case _ => ()
+ }
}
object History {
@@ -29,8 +38,11 @@ object History {
else new History(reader.getHistory)
def apply(): History = new History(
- try new JHistory(new File(userHome, ScalaHistoryFile))
- // do not store history if error
- catch { case _: Exception => new JHistory() }
+ try new FileHistory(new File(userHome, ScalaHistoryFile))
+ catch {
+ case x: Exception =>
+ Console.println("Error creating file history: memory history only. " + x)
+ new MemoryHistory()
+ }
)
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala b/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
index 0d71822172..153c0b42ed 100644
--- a/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/JLineReader.scala
@@ -7,34 +7,43 @@ package scala.tools.nsc
package interpreter
import java.io.File
-import jline.{ ConsoleReader, ArgumentCompletor, History => JHistory }
+import jline.console.ConsoleReader
+import jline.console.completer._
+import jline.console.history.{ History => JHistory }
/** Reads from the console using JLine */
class JLineReader(interpreter: Interpreter) extends InteractiveReader {
def this() = this(null)
- override lazy val history = Some(History(consoleReader))
+ override lazy val history = {
+ val h = History(consoleReader)
+ system addShutdownHook {
+ repldbg("Flushing history")
+ h.flush()
+ }
+ Some(h)
+ }
override lazy val completion = Option(interpreter) map (x => new Completion(x))
- override def init() = consoleReader.getTerminal().initializeTerminal()
+ override def init() = consoleReader.getTerminal().init()
override def redrawLine() = {
- consoleReader.flushConsole()
+ consoleReader.flush()
consoleReader.drawLine()
- consoleReader.flushConsole()
+ consoleReader.flush()
}
val consoleReader = {
- val r = new jline.ConsoleReader()
- r setHistory (History().jhistory)
+ val r = new ConsoleReader()
+ r setHistory (History().jhistory) // placeholder
r setBellEnabled false
completion foreach { c =>
- r addCompletor c.jline
- r setAutoprintThreshhold 250
+ r addCompleter c.jline
+ r setAutoprintThreshold 250 // max completion candidates without warning
}
r
}
- override def currentLine: String = consoleReader.getCursorBuffer.getBuffer.toString
+ override def currentLine: String = consoleReader.getCursorBuffer.buffer.toString
def readOneLine(prompt: String) = consoleReader readLine prompt
val interactive = true
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/Parsed.scala b/src/compiler/scala/tools/nsc/interpreter/Parsed.scala
index d5953d3a23..c36bfd9299 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Parsed.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Parsed.scala
@@ -6,7 +6,7 @@
package scala.tools.nsc
package interpreter
-import jline.ArgumentCompletor.{ ArgumentDelimiter, ArgumentList }
+import jline.console.completer.ArgumentCompleter.{ ArgumentDelimiter, ArgumentList }
import util.returning
/** One instance of a command buffer.
diff --git a/src/compiler/scala/tools/nsc/interpreter/package.scala b/src/compiler/scala/tools/nsc/interpreter/package.scala
index c57874e59a..d732719d62 100644
--- a/src/compiler/scala/tools/nsc/interpreter/package.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/package.scala
@@ -6,6 +6,13 @@
package scala.tools.nsc
package object interpreter {
+ private[nsc] val DebugProperty = "scala.repl.debug"
+ private[nsc] var _debug = false
+ private[nsc] def isReplDebug = _debug || (system.props contains DebugProperty)
+
+ /** Debug output */
+ def repldbg(msg: String) = if (isReplDebug) Console println msg
+
/** Tracing */
def tracing[T](msg: String)(x: T): T = { println("(" + msg + ") " + x) ; x }
diff --git a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
index 27bdd8a391..1e03de44a0 100644
--- a/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
+++ b/src/compiler/scala/tools/nsc/settings/ScalaSettings.scala
@@ -137,7 +137,8 @@ trait ScalaSettings extends AbsScalaSettings with StandardScalaSettings {
BooleanSetting ("-Ybuild-manager-debug", "Generate debug information for the Refined Build Manager compiler.")
val Ytyperdebug = BooleanSetting ("-Ytyper-debug", "Trace all type assignements.")
val Ypmatdebug = BooleanSetting ("-Ypmat-debug", "Trace all pattern matcher activity.")
- val Yrepldebug = BooleanSetting ("-Yrepl-debug", "Trace all repl activity.")
+ val Yrepldebug = BooleanSetting ("-Yrepl-debug", "Trace all repl activity.") .
+ withPostSetHook(set => interpreter._debug = true)
val Ycompletion = BooleanSetting ("-Ycompletion-debug", "Trace all tab completion activity.")
val Ypmatnaive = BooleanSetting ("-Ypmat-naive", "Desugar matches as naively as possible.")
val Ymurmur = BooleanSetting ("-Ymurmur", "Use Murmur hash algorithm for case class generated hashCodes.")