Skip to content
This repository was archived by the owner on Sep 1, 2020. It is now read-only.

Commit 43139fa

Browse files
committed
Centralize dependencies on jline
Code that depends on jline is now in package `scala.tools.nsc.interpreter.jline`. To make this possible, remove the `entries` functionality from `History`, and add the `historicize` method. Also provide an overload for `asStrings`. Clean up a little along the way in `JLineHistory.scala` and `JLineReader.scala`. Next step: fall back to an embedded jline when the expected jline jar is not on the classpath. The gist of the refactor: https://gist.github.com/adriaanm/02e110d4da0a585480c1
1 parent 43a56fb commit 43139fa

15 files changed

+314
-273
lines changed

src/repl/scala/tools/nsc/interpreter/Delimited.scala

Lines changed: 0 additions & 41 deletions
This file was deleted.

src/repl/scala/tools/nsc/interpreter/ILoop.scala

Lines changed: 17 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -503,10 +503,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
503503
val errless = intp compileSources new BatchSourceFile("<pastie>", s"object pastel {\n$code\n}")
504504
if (errless) echo("The compiler reports no errors.")
505505
}
506-
def historicize(text: String) = history match {
507-
case jlh: JLineHistory => text.lines foreach jlh.add ; jlh.moveToEnd() ; true
508-
case _ => false
509-
}
506+
510507
def edit(text: String): Result = editor match {
511508
case Some(ed) =>
512509
val tmp = File.makeTemp()
@@ -522,7 +519,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
522519
val res = intp interpret edited
523520
if (res == IR.Incomplete) diagnose(edited)
524521
else {
525-
historicize(edited)
522+
history.historicize(edited)
526523
Result(lineToRecord = Some(edited), keepRunning = true)
527524
}
528525
case None => echo("Can't read edited text. Did you delete it?")
@@ -533,7 +530,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
533530
tmp.delete()
534531
}
535532
case None =>
536-
if (historicize(text)) echo("Placing text in recent history.")
533+
if (history.historicize(text)) echo("Placing text in recent history.")
537534
else echo(f"No EDITOR defined and you can't change history, echoing your text:%n$text")
538535
}
539536

@@ -565,10 +562,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
565562
}
566563
import scala.collection.JavaConverters._
567564
val index = (start - 1) max 0
568-
val text = history match {
569-
case jlh: JLineHistory => jlh.entries(index).asScala.take(len) map (_.value) mkString "\n"
570-
case _ => history.asStrings.slice(index, index + len) mkString "\n"
571-
}
565+
val text = history.asStrings(index, index + len) mkString "\n"
572566
edit(text)
573567
} catch {
574568
case _: NumberFormatException => echo(s"Bad range '$what'")
@@ -866,16 +860,18 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
866860
* with SimpleReader.
867861
*/
868862
def chooseReader(settings: Settings): InteractiveReader = {
869-
if (settings.Xnojline || Properties.isEmacsShell)
870-
SimpleReader()
871-
else try new JLineReader(
872-
if (settings.noCompletion) NoCompletion
873-
else new JLineCompletion(intp)
874-
)
875-
catch {
876-
case ex @ (_: Exception | _: NoClassDefFoundError) =>
877-
echo(f"Failed to created JLineReader: ${ex}%nFalling back to SimpleReader.")
878-
SimpleReader()
863+
def mkJLineReader(completer: () => Completion): InteractiveReader =
864+
try new jline.JLineReader(completer)
865+
catch {
866+
case ex@(_: Exception | _: NoClassDefFoundError) =>
867+
Console.println(f"Failed to created JLineReader: ${ex}%nFalling back to SimpleReader.")
868+
SimpleReader()
869+
}
870+
871+
if (settings.Xnojline || Properties.isEmacsShell) SimpleReader()
872+
else {
873+
if (settings.noCompletion) mkJLineReader(() => NoCompletion)
874+
else mkJLineReader(() => new JLineCompletion(intp))
879875
}
880876
}
881877

@@ -896,10 +892,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
896892
asyncMessage(power.banner)
897893
}
898894
// SI-7418 Now, and only now, can we enable TAB completion.
899-
in match {
900-
case x: JLineReader => x.consoleReader.postInit
901-
case _ =>
902-
}
895+
in.postInit()
903896
}
904897

905898
// start an interpreter with the given settings

src/repl/scala/tools/nsc/interpreter/InteractiveReader.scala

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import Properties.isMac
1313

1414
/** Reads lines from an input stream */
1515
trait InteractiveReader {
16+
def postInit(): Unit = {}
17+
1618
val interactive: Boolean
1719

1820
def reset(): Unit

src/repl/scala/tools/nsc/interpreter/JLineCompletion.scala

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import scala.reflect.internal.util.StringOps.longestCommonPrefix
1212

1313
// REPL completor - queries supplied interpreter for valid
1414
// completions based on current contents of buffer.
15+
// TODO: change class name to reflect it's not specific to jline (nor does it depend on it)
1516
class JLineCompletion(val intp: IMain) extends Completion with CompletionOutput {
1617
val global: intp.global.type = intp.global
1718
import global._

src/repl/scala/tools/nsc/interpreter/JLineReader.scala

Lines changed: 0 additions & 75 deletions
This file was deleted.

src/repl/scala/tools/nsc/interpreter/Parsed.scala

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,25 @@ package interpreter
88

99
import util.returning
1010

11+
trait Delimited {
12+
self: Parsed =>
13+
14+
def delimited: Char => Boolean
15+
def escapeChars: List[Char] = List('\\')
16+
17+
/** Break String into args based on delimiting function.
18+
*/
19+
protected def toArgs(s: String): List[String] =
20+
if (s == "") Nil
21+
else (s indexWhere isDelimiterChar) match {
22+
case -1 => List(s)
23+
case idx => (s take idx) :: toArgs(s drop (idx + 1))
24+
}
25+
26+
def isDelimiterChar(ch: Char) = delimited(ch)
27+
def isEscapeChar(ch: Char): Boolean = escapeChars contains ch
28+
}
29+
1130
/** One instance of a command buffer.
1231
*/
1332
class Parsed private (

src/repl/scala/tools/nsc/interpreter/ConsoleReaderHelper.scala renamed to src/repl/scala/tools/nsc/interpreter/Tabulators.scala

Lines changed: 3 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -3,60 +3,7 @@
33
* @author Paul Phillips
44
*/
55

6-
package scala.tools.nsc
7-
package interpreter
8-
9-
import jline.console.{ ConsoleReader, CursorBuffer }
10-
11-
trait ConsoleReaderHelper { _: ConsoleReader with Tabulator =>
12-
def isAcross: Boolean
13-
14-
def terminal = getTerminal()
15-
def width = terminal.getWidth()
16-
def height = terminal.getHeight()
17-
18-
def readOneKey(prompt: String): Int
19-
def eraseLine(): Unit
20-
21-
val marginSize = 3
22-
23-
private def morePrompt = "--More--"
24-
private def emulateMore(): Int = {
25-
val key = readOneKey(morePrompt)
26-
try key match {
27-
case '\r' | '\n' => 1
28-
case 'q' => -1
29-
case _ => height - 1
30-
}
31-
finally {
32-
eraseLine()
33-
// TODO: still not quite managing to erase --More-- and get
34-
// back to a scala prompt without another keypress.
35-
if (key == 'q') {
36-
putString(getPrompt())
37-
redrawLine()
38-
flush()
39-
}
40-
}
41-
}
42-
43-
override def printColumns(items: JCollection[_ <: CharSequence]): Unit =
44-
printColumns_(items: List[String])
45-
46-
private def printColumns_(items: List[String]): Unit = if (items exists (_ != "")) {
47-
val grouped = tabulate(items)
48-
var linesLeft = if (isPaginationEnabled()) height - 1 else Int.MaxValue
49-
grouped foreach { xs =>
50-
println(xs.mkString)
51-
linesLeft -= 1
52-
if (linesLeft <= 0) {
53-
linesLeft = emulateMore()
54-
if (linesLeft < 0)
55-
return
56-
}
57-
}
58-
}
59-
}
6+
package scala.tools.nsc.interpreter
607

618
trait Tabulator {
629
def isAcross: Boolean
@@ -72,7 +19,7 @@ trait Tabulator {
7219
)
7320
protected def columnize(ss: Seq[String]): Seq[Seq[String]] = ss map (s => Seq(s))
7421
protected def printMultiLineColumns(items: Seq[String]): Seq[Seq[String]] = {
75-
import SimpleMath._
22+
import scala.tools.nsc.interpreter.SimpleMath._
7623
val longest = (items map (_.length)).max
7724
val columnWidth = longest + marginSize
7825
val maxcols = (
@@ -101,7 +48,7 @@ trait Tabulator {
10148
/** Adjust the column width and number of columns to minimize the row count. */
10249
trait VariColumnTabulator extends Tabulator {
10350
override protected def printMultiLineColumns(items: Seq[String]): Seq[Seq[String]] = {
104-
import SimpleMath._
51+
import scala.tools.nsc.interpreter.SimpleMath._
10552
val longest = (items map (_.length)).max
10653
val shortest = (items map (_.length)).min
10754
val fattest = longest + marginSize

0 commit comments

Comments
 (0)