From a449b1ff2dff2891c38ef59331c30cde755fc0c9 Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Thu, 12 Dec 2019 18:50:53 -0800 Subject: [PATCH] Move JLine apis into LineReader It is better that sbt not expose the implementation detail that LineReader is implemented by JLine. Other terminal related apis should be handled by sbt.internal.util.Terminal. --- .../scala/sbt/internal/util/LineReader.scala | 56 ++++++++++++++----- .../src/main/scala/sbt/BasicCommands.scala | 6 +- .../scala/sbt/internal/ConsoleChannel.scala | 7 ++- .../sbt/internal/client/NetworkClient.scala | 4 +- 4 files changed, 55 insertions(+), 18 deletions(-) diff --git a/internal/util-complete/src/main/scala/sbt/internal/util/LineReader.scala b/internal/util-complete/src/main/scala/sbt/internal/util/LineReader.scala index ab082c600..dfce336b3 100644 --- a/internal/util-complete/src/main/scala/sbt/internal/util/LineReader.scala +++ b/internal/util-complete/src/main/scala/sbt/internal/util/LineReader.scala @@ -16,6 +16,36 @@ import sbt.internal.util.complete.Parser import scala.annotation.tailrec import scala.concurrent.duration._ +trait LineReader { + def readLine(prompt: String, mask: Option[Char] = None): Option[String] + def redraw(): Unit = () +} + +object LineReader { + val HandleCONT = + !java.lang.Boolean.getBoolean("sbt.disable.cont") && Signals.supported(Signals.CONT) + val MaxHistorySize = 500 + + def createReader(historyPath: Option[File], in: InputStream): ConsoleReader = { + val cr = Terminal.createReader(in) + cr.setExpandEvents(false) // https://issues.scala-lang.org/browse/SI-7650 + cr.setBellEnabled(false) + val h = historyPath match { + case None => new MemoryHistory + case Some(file) => new FileHistory(file): MemoryHistory + } + h.setMaxSize(MaxHistorySize) + cr.setHistory(h) + cr + } + + def simple( + historyPath: Option[File], + handleCONT: Boolean = HandleCONT, + injectThreadSleep: Boolean = false + ): LineReader = new SimpleReader(historyPath, handleCONT, injectThreadSleep) +} + abstract class JLine extends LineReader { protected[this] def handleCONT: Boolean protected[this] def reader: ConsoleReader @@ -92,6 +122,7 @@ abstract class JLine extends LineReader { } } +@deprecated("Use LineReader apis", "1.4.0") private[sbt] object JLine { @deprecated("For binary compatibility only", "1.4.0") protected[this] val originalIn = new FileInputStream(FileDescriptor.in) @@ -117,8 +148,10 @@ private[sbt] object JLine { def usingTerminal[T](f: jline.Terminal => T): T = Terminal.withCanonicalIn(f(Terminal.deprecatedTeminal)) + @deprecated("unused", "1.4.0") def createReader(): ConsoleReader = createReader(None, Terminal.wrappedSystemIn) + @deprecated("Use LineReader.createReader", "1.4.0") def createReader(historyPath: Option[File], in: InputStream): ConsoleReader = { val cr = Terminal.createReader(in) cr.setExpandEvents(false) // https://issues.scala-lang.org/browse/SI-7650 @@ -135,16 +168,18 @@ private[sbt] object JLine { @deprecated("Avoid referencing JLine directly. Use Terminal.withRawSystemIn instead.", "1.4.0") def withJLine[T](action: => T): T = Terminal.withRawSystemIn(action) + @deprecated("Use LineReader.simple instead", "1.4.0") def simple( historyPath: Option[File], - handleCONT: Boolean = HandleCONT, + handleCONT: Boolean = LineReader.HandleCONT, injectThreadSleep: Boolean = false ): SimpleReader = new SimpleReader(historyPath, handleCONT, injectThreadSleep) - val MaxHistorySize = 500 + @deprecated("Use LineReader.MaxHistorySize", "1.4.0") + val MaxHistorySize = LineReader.MaxHistorySize - val HandleCONT = - !java.lang.Boolean.getBoolean("sbt.disable.cont") && Signals.supported(Signals.CONT) + @deprecated("Use LineReader.HandleCONT", "1.4.0") + val HandleCONT = LineReader.HandleCONT } @deprecated("For binary compatibility only", "1.4.0") @@ -172,11 +207,6 @@ private[sbt] class InputStreamWrapper(is: InputStream, val poll: Duration) } } -trait LineReader { - def readLine(prompt: String, mask: Option[Char] = None): Option[String] - def redraw(): Unit = () -} - final class FullReader( historyPath: Option[File], complete: Parser[_], @@ -187,11 +217,11 @@ final class FullReader( def this( historyPath: Option[File], complete: Parser[_], - handleCONT: Boolean = JLine.HandleCONT, + handleCONT: Boolean = LineReader.HandleCONT, injectThreadSleep: Boolean = false ) = this(historyPath, complete, handleCONT, JLine.makeInputStream(injectThreadSleep)) protected[this] val reader: ConsoleReader = { - val cr = JLine.createReader(historyPath, inputStream) + val cr = LineReader.createReader(historyPath, inputStream) sbt.internal.util.complete.JLineCompletion.installCustomCompletor(cr, complete) cr } @@ -205,7 +235,7 @@ class SimpleReader private[sbt] ( def this(historyPath: Option[File], handleCONT: Boolean, injectThreadSleep: Boolean) = this(historyPath, handleCONT, Terminal.wrappedSystemIn) protected[this] val reader: ConsoleReader = - JLine.createReader(historyPath, inputStream) + LineReader.createReader(historyPath, inputStream) } -object SimpleReader extends SimpleReader(None, JLine.HandleCONT, false) +object SimpleReader extends SimpleReader(None, LineReader.HandleCONT, false) diff --git a/main-command/src/main/scala/sbt/BasicCommands.scala b/main-command/src/main/scala/sbt/BasicCommands.scala index 0fe030fb6..e6de5b0c1 100644 --- a/main-command/src/main/scala/sbt/BasicCommands.scala +++ b/main-command/src/main/scala/sbt/BasicCommands.scala @@ -9,7 +9,7 @@ package sbt import java.nio.file.Paths import sbt.util.Level -import sbt.internal.util.{ AttributeKey, FullReader, JLine, Terminal } +import sbt.internal.util.{ AttributeKey, FullReader, LineReader, Terminal } import sbt.internal.util.complete.{ Completion, Completions, @@ -34,7 +34,9 @@ import BasicKeys._ import java.io.File import sbt.io.IO +import sbt.util.Level +import scala.Function.tupled import scala.collection.mutable.ListBuffer import scala.util.control.NonFatal @@ -374,7 +376,7 @@ object BasicCommands { val history = (s get historyPath) getOrElse (new File(s.baseDir, ".history")).some val prompt = (s get shellPrompt) match { case Some(pf) => pf(s); case None => "> " } val reader = - new FullReader(history, s.combinedParser, JLine.HandleCONT, Terminal.wrappedSystemIn) + new FullReader(history, s.combinedParser, LineReader.HandleCONT, Terminal.wrappedSystemIn) val line = reader.readLine(prompt) line match { case Some(line) => diff --git a/main-command/src/main/scala/sbt/internal/ConsoleChannel.scala b/main-command/src/main/scala/sbt/internal/ConsoleChannel.scala index 11bee3a2a..f16a0ee9a 100644 --- a/main-command/src/main/scala/sbt/internal/ConsoleChannel.scala +++ b/main-command/src/main/scala/sbt/internal/ConsoleChannel.scala @@ -29,7 +29,12 @@ private[sbt] final class ConsoleChannel(val name: String) extends CommandChannel private val history = s.get(historyPath).getOrElse(Some(new File(s.baseDir, ".history"))) private val prompt = getPrompt(s) private val reader = - new FullReader(history, s.combinedParser, JLine.HandleCONT, Terminal.throwOnClosedSystemIn) + new FullReader( + history, + s.combinedParser, + LineReader.HandleCONT, + Terminal.throwOnClosedSystemIn + ) setDaemon(true) start() override def run(): Unit = diff --git a/main-command/src/main/scala/sbt/internal/client/NetworkClient.scala b/main-command/src/main/scala/sbt/internal/client/NetworkClient.scala index 1de8de473..c01d99340 100644 --- a/main-command/src/main/scala/sbt/internal/client/NetworkClient.scala +++ b/main-command/src/main/scala/sbt/internal/client/NetworkClient.scala @@ -15,7 +15,7 @@ import java.util.concurrent.atomic.{ AtomicBoolean, AtomicReference } import sbt.internal.langserver.{ LogMessageParams, MessageType, PublishDiagnosticsParams } import sbt.internal.protocol._ -import sbt.internal.util.{ ConsoleAppender, JLine } +import sbt.internal.util.{ ConsoleAppender, LineReader } import sbt.io.IO import sbt.io.syntax._ import sbt.protocol._ @@ -216,7 +216,7 @@ class NetworkClient(configuration: xsbti.AppConfiguration, arguments: List[Strin } def shell(): Unit = { - val reader = JLine.simple(None, JLine.HandleCONT, injectThreadSleep = true) + val reader = LineReader.simple(None, LineReader.HandleCONT, injectThreadSleep = true) while (running.get) { reader.readLine("> ", None) match { case Some("shutdown") =>