mirror of https://github.com/sbt/sbt.git
Add Terminal.withRawOutput api
In the scala console, it's essential that we not process the bytes that are written to the terminal by jline.
This commit is contained in:
parent
bc4fe0a31a
commit
25e83d8fec
|
|
@ -79,7 +79,7 @@ object LineReader {
|
|||
historyPath.foreach(f => reader.setVariable(JLineReader.HISTORY_FILE, f))
|
||||
new LineReader {
|
||||
override def readLine(prompt: String, mask: Option[Char]): Option[String] = {
|
||||
try terminal.withRawSystemIn {
|
||||
try terminal.withRawInput {
|
||||
Option(mask.map(reader.readLine(prompt, _)).getOrElse(reader.readLine(prompt)))
|
||||
} catch {
|
||||
case e: EndOfFileException =>
|
||||
|
|
@ -240,7 +240,7 @@ private[sbt] object JLine {
|
|||
}
|
||||
|
||||
@deprecated("Avoid referencing JLine directly.", "1.4.0")
|
||||
def withJLine[T](action: => T): T = Terminal.get.withRawSystemIn(action)
|
||||
def withJLine[T](action: => T): T = Terminal.get.withRawInput(action)
|
||||
|
||||
@deprecated("Use LineReader.simple instead", "1.4.0")
|
||||
def simple(
|
||||
|
|
|
|||
|
|
@ -127,11 +127,12 @@ trait Terminal extends AutoCloseable {
|
|||
private[sbt] def setSize(width: Int, height: Int): Unit
|
||||
|
||||
private[sbt] def name: String
|
||||
private[sbt] def withRawSystemIn[T](f: => T): T = f
|
||||
private[sbt] def withRawInput[T](f: => T): T = f
|
||||
private[sbt] def withCanonicalIn[T](f: => T): T = f
|
||||
private[sbt] def write(bytes: Int*): Unit
|
||||
private[sbt] def printStream: PrintStream
|
||||
private[sbt] def withPrintStream[T](f: PrintStream => T): T
|
||||
private[sbt] def withRawOutput[R](f: => R): R
|
||||
private[sbt] def restore(): Unit = {}
|
||||
private[sbt] val progressState = new ProgressState(1)
|
||||
private[this] val promptHolder: AtomicReference[Prompt] = new AtomicReference(Prompt.Running)
|
||||
|
|
@ -330,10 +331,11 @@ object Terminal {
|
|||
override private[sbt] def setAttributes(attributes: Map[String, String]): Unit =
|
||||
t.setAttributes(attributes)
|
||||
override private[sbt] def setSize(width: Int, height: Int): Unit = t.setSize(width, height)
|
||||
override def withRawSystemIn[T](f: => T): T = t.withRawSystemIn(f)
|
||||
override def withRawInput[T](f: => T): T = t.withRawInput(f)
|
||||
override def withCanonicalIn[T](f: => T): T = t.withCanonicalIn(f)
|
||||
override def printStream: PrintStream = t.printStream
|
||||
override def withPrintStream[T](f: PrintStream => T): T = t.withPrintStream(f)
|
||||
override private[sbt] def withRawOutput[R](f: => R): R = t.withRawOutput(f)
|
||||
override def restore(): Unit = t.restore()
|
||||
override def close(): Unit = {}
|
||||
override private[sbt] def write(bytes: Int*): Unit = t.write(bytes: _*)
|
||||
|
|
@ -737,8 +739,8 @@ object Terminal {
|
|||
private[sbt] def createReader(term: Terminal, prompt: Prompt): ConsoleReader = {
|
||||
new ConsoleReader(term.inputStream, term.outputStream, term.toJLine) {
|
||||
override def readLine(prompt: String, mask: Character): String =
|
||||
term.withRawSystemIn(super.readLine(prompt, mask))
|
||||
override def readLine(prompt: String): String = term.withRawSystemIn(super.readLine(prompt))
|
||||
term.withRawInput(super.readLine(prompt, mask))
|
||||
override def readLine(prompt: String): String = term.withRawInput(super.readLine(prompt))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -782,7 +784,7 @@ object Terminal {
|
|||
override private[sbt] def setSize(width: Int, height: Int): Unit =
|
||||
system.setSize(new org.jline.terminal.Size(width, height))
|
||||
|
||||
override def withRawSystemIn[T](f: => T): T = term.synchronized {
|
||||
override def withRawInput[T](f: => T): T = term.synchronized {
|
||||
val prev = JLine3.enterRawMode(system)
|
||||
try f
|
||||
catch { case _: InterruptedIOException => throw new InterruptedException } finally {
|
||||
|
|
@ -812,6 +814,7 @@ object Terminal {
|
|||
val out: OutputStream,
|
||||
override private[sbt] val name: String
|
||||
) extends Terminal {
|
||||
private[this] val rawMode = new AtomicBoolean(false)
|
||||
private[this] val writeLock = new AnyRef
|
||||
private[this] val writeableInputStream = in match {
|
||||
case w: WriteableInputStream => w
|
||||
|
|
@ -852,7 +855,7 @@ object Terminal {
|
|||
override def flush(): Unit = combinedOutputStream.flush()
|
||||
}
|
||||
private def doWrite(bytes: Array[Byte]): Unit =
|
||||
progressState.write(TerminalImpl.this, bytes, rawPrintStream, hasProgress.get)
|
||||
progressState.write(TerminalImpl.this, bytes, rawPrintStream, hasProgress.get && !rawMode.get)
|
||||
override private[sbt] val printStream: PrintStream = new LinePrintStream(outputStream)
|
||||
override def inputStream: InputStream = writeableInputStream
|
||||
|
||||
|
|
@ -867,6 +870,11 @@ object Terminal {
|
|||
case _ => (0, 0)
|
||||
}
|
||||
|
||||
private[sbt] def withRawOutput[R](f: => R): R = {
|
||||
rawMode.set(true)
|
||||
try f
|
||||
finally rawMode.set(false)
|
||||
}
|
||||
private[this] val rawPrintStream: PrintStream = new LinePrintStream(combinedOutputStream)
|
||||
override def withPrintStream[T](f: PrintStream => T): T =
|
||||
writeLock.synchronized(f(rawPrintStream))
|
||||
|
|
@ -904,5 +912,6 @@ object Terminal {
|
|||
new PrintStream(outputStream, false)
|
||||
override private[sbt] def withPrintStream[T](f: java.io.PrintStream => T): T = f(printStream)
|
||||
override private[sbt] def write(bytes: Int*): Unit = {}
|
||||
override private[sbt] def withRawOutput[R](f: => R): R = f
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -66,7 +66,9 @@ final class Console(compiler: AnalyzingCompiler) {
|
|||
val previous = sys.props.get("scala.color").getOrElse("auto")
|
||||
try {
|
||||
sys.props("scala.color") = if (terminal.isColorEnabled) "true" else "false"
|
||||
terminal.withRawSystemIn(Run.executeTrapExit(console0, log))
|
||||
terminal.withRawOutput {
|
||||
terminal.withRawInput(Run.executeTrapExit(console0, log))
|
||||
}
|
||||
} finally {
|
||||
sys.props("scala.color") = previous
|
||||
}
|
||||
|
|
|
|||
|
|
@ -885,7 +885,7 @@ class NetworkClient(
|
|||
if (!stopped.get()) read()
|
||||
}
|
||||
}
|
||||
try Terminal.console.withRawSystemIn(read())
|
||||
try Terminal.console.withRawInput(read())
|
||||
catch { case NonFatal(_) => stopped.set(true) }
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1503,7 +1503,7 @@ object Defaults extends BuildCommon {
|
|||
Some(s => {
|
||||
def print(st: String) = { scala.Console.out.print(st); scala.Console.out.flush() }
|
||||
print(s)
|
||||
Terminal.get.withRawSystemIn {
|
||||
Terminal.get.withRawInput {
|
||||
try Terminal.get.inputStream.read match {
|
||||
case -1 | -2 => None
|
||||
case b =>
|
||||
|
|
|
|||
|
|
@ -114,7 +114,7 @@ private[sbt] object xMain {
|
|||
case _: ServerAlreadyBootingException
|
||||
if System.console != null && !Terminal.startedByRemoteClient =>
|
||||
println("sbt server is already booting. Create a new server? y/n (default y)")
|
||||
val exit = Terminal.get.withRawSystemIn(System.in.read) match {
|
||||
val exit = Terminal.get.withRawInput(System.in.read) match {
|
||||
case 110 => Some(Exit(1))
|
||||
case _ => None
|
||||
}
|
||||
|
|
@ -835,7 +835,7 @@ object BuiltinCommands {
|
|||
@tailrec
|
||||
private[this] def doLoadFailed(s: State, loadArg: String): State = {
|
||||
s.log.warn("Project loading failed: (r)etry, (q)uit, (l)ast, or (i)gnore? (default: r)")
|
||||
val result = try Terminal.get.withRawSystemIn(System.in.read) match {
|
||||
val result = try Terminal.get.withRawInput(System.in.read) match {
|
||||
case -1 => 'q'.toInt
|
||||
case b => b
|
||||
} catch { case _: ClosedChannelException => 'q' }
|
||||
|
|
|
|||
|
|
@ -759,7 +759,7 @@ private[sbt] object Continuous extends DeprecatedContinuous {
|
|||
}
|
||||
}
|
||||
|
||||
terminal.withRawSystemIn(impl())
|
||||
terminal.withRawInput(impl())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue