Created
June 17, 2015 20:34
-
-
Save anonymous/a76f519f705bd2f85952 to your computer and use it in GitHub Desktop.
summary of jline refactoring
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- 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