mirror of https://github.com/sbt/sbt.git
Fix #552 Compensate for JLine's absent EOF detection.
In the unsupported terminal mode, JLine treats a broken stdin as an endless stream of empty lines. This is problematic for idea-sbt-plugin: if the IntelliJ process is forcibly killed and leaves the child SBT process running, it consumes considerable CPU processing these. Patching JLine itself would be the cleanest solution (the change has already been applied to JLine 2), but I've shied away from that and instead wrapped the InputStream that is read by JLine to intercept the result of -1 from read(). When this happens, the flat `inputEof` is set to true.
This commit is contained in:
parent
c8ffd6a54d
commit
efa362c583
|
|
@ -3,14 +3,17 @@
|
||||||
*/
|
*/
|
||||||
package sbt
|
package sbt
|
||||||
|
|
||||||
import jline.{Completor, ConsoleReader, History}
|
import jline.{ConsoleReader, History}
|
||||||
import java.io.{File,PrintWriter}
|
import java.io.{File, InputStream, PrintWriter}
|
||||||
import complete.Parser
|
import complete.Parser
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean
|
||||||
|
|
||||||
abstract class JLine extends LineReader
|
abstract class JLine extends LineReader
|
||||||
{
|
{
|
||||||
protected[this] val handleCONT: Boolean
|
protected[this] val handleCONT: Boolean
|
||||||
protected[this] val reader: ConsoleReader
|
protected[this] val reader: ConsoleReader
|
||||||
|
/** Is the input stream at EOF? Compensates for absent EOF detection in JLine's UnsupportedTerminal. */
|
||||||
|
protected[this] val inputEof = new AtomicBoolean(false)
|
||||||
protected[this] val historyPath: Option[File]
|
protected[this] val historyPath: Option[File]
|
||||||
|
|
||||||
def readLine(prompt: String, mask: Option[Char] = None) = JLine.withJLine { unsynchronizedReadLine(prompt, mask) }
|
def readLine(prompt: String, mask: Option[Char] = None) = JLine.withJLine { unsynchronizedReadLine(prompt, mask) }
|
||||||
|
|
@ -39,10 +42,14 @@ abstract class JLine extends LineReader
|
||||||
else
|
else
|
||||||
readLineDirectRaw(prompt, mask)
|
readLineDirectRaw(prompt, mask)
|
||||||
private[this] def readLineDirectRaw(prompt: String, mask: Option[Char]): String =
|
private[this] def readLineDirectRaw(prompt: String, mask: Option[Char]): String =
|
||||||
mask match {
|
{
|
||||||
|
val line = mask match {
|
||||||
case Some(m) => reader.readLine(prompt, m)
|
case Some(m) => reader.readLine(prompt, m)
|
||||||
case None => reader.readLine(prompt)
|
case None => reader.readLine(prompt)
|
||||||
}
|
}
|
||||||
|
if (inputEof.get) null else line
|
||||||
|
}
|
||||||
|
|
||||||
private[this] def resume()
|
private[this] def resume()
|
||||||
{
|
{
|
||||||
jline.Terminal.resetTerminal
|
jline.Terminal.resetTerminal
|
||||||
|
|
@ -109,6 +116,16 @@ final class FullReader(val historyPath: Option[File], complete: Parser[_], val h
|
||||||
protected[this] val reader =
|
protected[this] val reader =
|
||||||
{
|
{
|
||||||
val cr = new ConsoleReader
|
val cr = new ConsoleReader
|
||||||
|
if (!cr.getTerminal.isSupported) {
|
||||||
|
val input = cr.getInput
|
||||||
|
cr.setInput(new InputStream {
|
||||||
|
def read(): Int = {
|
||||||
|
val c = input.read()
|
||||||
|
if (c == -1) inputEof.set(true)
|
||||||
|
c
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
cr.setBellEnabled(false)
|
cr.setBellEnabled(false)
|
||||||
sbt.complete.JLineCompletion.installCustomCompletor(cr, complete)
|
sbt.complete.JLineCompletion.installCustomCompletor(cr, complete)
|
||||||
cr
|
cr
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue