Skip to content

Instantly share code, notes, and snippets.

Created June 17, 2015 20:34
Show Gist options
  • Save anonymous/a76f519f705bd2f85952 to your computer and use it in GitHub Desktop.
Save anonymous/a76f519f705bd2f85952 to your computer and use it in GitHub Desktop.
summary of jline refactoring
--- src/repl/scala/tools/nsc/interpreter/JLineReader.scala 2015-06-17 11:43:05.000000000 -0700
+++ src/repl-jline/scala/tools/nsc/interpreter/jline/JLineReader.scala 2015-06-17 11:30:53.000000000 -0700
@@ -1,101 +1,72 @@
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
+/** NSC -- new Scala compiler
+ *
+ * Copyright 2005-2015 LAMP/EPFL
* @author Stepan Koltsov
+ * @author Adriaan Moors
*/
-package scala.tools.nsc
-package interpreter
+package scala.tools.nsc.interpreter.jline
-import jline.console.ConsoleReader
-import jline.console.completer._
-import session._
-import Completion._
+import java.util.{Collection => JCollection, List => JList}
+
+import _root_.jline.{console => jconsole}
+import jconsole.completer.{Completer, ArgumentCompleter}
+import jconsole.history.{History => JHistory}
+
+
+import scala.tools.nsc.interpreter
+import scala.tools.nsc.interpreter.Completion
+import scala.tools.nsc.interpreter.Completion.Candidates
+import scala.tools.nsc.interpreter.session.History
/**
* Reads from the console using JLine.
+ *
+ * Eagerly instantiates all relevant JLine classes, so that we can detect linkage errors on `new JLineReader` and retry.
*/
-class JLineReader(_completion: => Completion) extends InteractiveReader {
+class InteractiveReader(completer: () => Completion) extends interpreter.InteractiveReader {
val interactive = true
- val consoleReader = new JLineConsoleReader()
- lazy val completion = _completion
- lazy val history: JLineHistory = JLineHistory()
+ val history: History = new JLineHistory.JLineFileHistory()
- private def term = consoleReader.getTerminal()
- def reset() = term.reset()
+ private val consoleReader = {
+ val reader = new JLineConsoleReader()
- def scalaToJline(tc: ScalaCompleter): Completer = new Completer {
- def complete(_buf: String, cursor: Int, candidates: JList[CharSequence]): Int = {
- val buf = if (_buf == null) "" else _buf
- val Candidates(newCursor, newCandidates) = tc.complete(buf, cursor)
- newCandidates foreach (candidates add _)
- newCursor
- }
- }
-
- class JLineConsoleReader extends ConsoleReader with ConsoleReaderHelper with VariColumnTabulator {
- val isAcross = interpreter.`package`.isAcross
-
- this setPaginationEnabled interpreter.`package`.isPaged
+ reader setPaginationEnabled interpreter.`package`.isPaged
// ASAP
- this setExpandEvents false
+ reader setExpandEvents false
- // working around protected/trait/java insufficiencies.
- def goBack(num: Int): Unit = back(num)
- if ((history: History) ne NoHistory)
- this setHistory history
+ reader setHistory history.asInstanceOf[JHistory]
- def readOneKey(prompt: String) = {
- this.print(prompt)
- this.flush()
- this.readCharacter()
+ reader
}
- def eraseLine() = consoleReader.resetPromptLine("", "", 0)
- def redrawLineAndFlush(): Unit = { flush() ; drawLine() ; flush() }
- // A hook for running code after the repl is done initializing.
- lazy val postInit: Unit = {
- this setBellEnabled false
+ private[this] var _completion: Completion = interpreter.NoCompletion
+ def completion: Completion = _completion
- if (completion ne NoCompletion) {
- val argCompletor: ArgumentCompleter =
- new ArgumentCompleter(new JLineDelimiter, scalaToJline(completion.completer()))
- argCompletor setStrict false
+ override def postInit() = {
+ _completion = completer()
- this addCompleter argCompletor
- this setAutoprintThreshold 400 // max completion candidates without warning
- }
- }
+ consoleReader.initCompletion(completion)
}
+ def reset() = consoleReader.getTerminal().reset()
def redrawLine() = consoleReader.redrawLineAndFlush()
- def readOneLine(prompt: String) = consoleReader readLine prompt
- def readOneKey(prompt: String) = consoleReader readOneKey prompt
+ def readOneLine(prompt: String) = consoleReader.readLine(prompt)
+ def readOneKey(prompt: String) = consoleReader.readOneKey(prompt)
}
-/* NSC -- new Scala compiler
- * Copyright 2005-2013 LAMP/EPFL
- * @author Paul Phillips
- */
-
-package scala.tools.nsc
-package interpreter
-
-import jline.console.{ ConsoleReader, CursorBuffer }
-
-trait ConsoleReaderHelper { _: ConsoleReader with Tabulator =>
- def isAcross: Boolean
-
- def terminal = getTerminal()
- def width = terminal.getWidth()
- def height = terminal.getHeight()
-
- def readOneKey(prompt: String): Int
- def eraseLine(): Unit
+// implements a jline interface
+private class JLineConsoleReader extends jconsole.ConsoleReader with interpreter.VariColumnTabulator {
+ val isAcross = interpreter.`package`.isAcross
val marginSize = 3
+ def width = getTerminal.getWidth()
+ def height = getTerminal.getHeight()
+
private def morePrompt = "--More--"
+
private def emulateMore(): Int = {
val key = readOneKey(morePrompt)
try key match {
@@ -115,8 +86,10 @@
}
}
- override def printColumns(items: JCollection[_ <: CharSequence]): Unit =
+ override def printColumns(items: JCollection[_ <: CharSequence]): Unit = {
+ import scala.tools.nsc.interpreter.javaCharSeqCollectionToScala
printColumns_(items: List[String])
+ }
private def printColumns_(items: List[String]): Unit = if (items exists (_ != "")) {
val grouped = tabulate(items)
@@ -131,4 +104,40 @@
}
}
}
+
+ def readOneKey(prompt: String) = {
+ this.print(prompt)
+ this.flush()
+ this.readCharacter()
+ }
+
+ def eraseLine() = resetPromptLine("", "", 0)
+
+ def redrawLineAndFlush(): Unit = {
+ flush(); drawLine(); flush()
+ }
+
+ // A hook for running code after the repl is done initializing.
+ def initCompletion(completion: Completion): Unit = {
+ this setBellEnabled false
+
+ if (completion ne interpreter.NoCompletion) {
+ val jlineCompleter = new ArgumentCompleter(new JLineDelimiter,
+ new Completer {
+ val tc = completion.completer()
+ def complete(_buf: String, cursor: Int, candidates: JList[CharSequence]): Int = {
+ val buf = if (_buf == null) "" else _buf
+ val Candidates(newCursor, newCandidates) = tc.complete(buf, cursor)
+ newCandidates foreach (candidates add _)
+ newCursor
+ }
+ }
+ )
+
+ jlineCompleter setStrict false
+
+ this addCompleter jlineCompleter
+ this setAutoprintThreshold 400 // max completion candidates without warning
+ }
+ }
}
--- src/repl/scala/tools/nsc/interpreter/session/JLineHistory.scala 2015-06-17 11:45:26.000000000 -0700
+++ src/repl-jline/scala/tools/nsc/interpreter/jline/JLineHistory.scala 2015-06-17 11:30:53.000000000 -0700
@@ -3,9 +3,17 @@
* @author Paul Phillips
*/
-package scala.tools.nsc
-package interpreter
-package session
+package scala.tools.nsc.interpreter.jline
+
+import java.util.{Iterator => JIterator, ListIterator => JListIterator}
+
+import _root_.jline.{console => jconsole}
+import jconsole.history.History.{Entry => JEntry}
+import jconsole.history.{History => JHistory}
+
+import scala.tools.nsc.interpreter
+import scala.tools.nsc.interpreter.session.{History, SimpleHistory}
+
/** A straight scalification of the jline interface which mixes
* in the sparse jline-independent one too.
@@ -30,20 +38,40 @@
def moveToLast(): Boolean
def moveTo(index: Int): Boolean
def moveToEnd(): Unit
+
+ override def historicize(text: String): Boolean = {
+ text.lines foreach add
+ moveToEnd()
+ true
+ }
}
object JLineHistory {
class JLineFileHistory extends SimpleHistory with FileBackedHistory {
override def add(item: CharSequence): Unit = {
if (!isEmpty && last == item)
- repldbg("Ignoring duplicate entry '" + item + "'")
+ interpreter.repldbg("Ignoring duplicate entry '" + item + "'")
else {
super.add(item)
addLineToFile(item)
}
}
override def toString = "History(size = " + size + ", index = " + index + ")"
+
+ import scala.collection.JavaConverters._
+
+ override def asStrings(from: Int, to: Int): List[String] =
+ entries(from).asScala.take(to - from).map(_.value.toString).toList
+
+ case class Entry(index: Int, value: CharSequence) extends JEntry {
+ override def toString = value.toString
+ }
+
+ private def toEntries(): Seq[JEntry] = buf.zipWithIndex map { case (x, i) => Entry(i, x)}
+ def entries(idx: Int): JListIterator[JEntry] = toEntries().asJava.listIterator(idx)
+ def entries(): JListIterator[JEntry] = toEntries().asJava.listIterator()
+ def iterator: JIterator[JEntry] = toEntries().iterator.asJava
}
- def apply(): JLineHistory = try new JLineFileHistory catch { case x: Exception => new SimpleHistory() }
+ def apply(): History = try new JLineFileHistory catch { case x: Exception => new SimpleHistory() }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment