From 76128a9380848ac90e3a6c82cc99d67029befd3b Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Tue, 6 Oct 2020 09:10:39 -0700 Subject: [PATCH] Read input from dumb terminals On my computer with jEdit, input is not read because the console input stream was overridden to be a blocking input stream that never returned input. While debugging the server test hangs, I added some logic to prevent us from trying to read from System.in when System.console == null but I now realize that was a mistake because of situations like ides or editors launching an sbt shell. --- .../main/scala/sbt/internal/util/Terminal.scala | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala b/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala index 829b2f3cb..741ce4d78 100644 --- a/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala +++ b/internal/util-logging/src/main/scala/sbt/internal/util/Terminal.scala @@ -306,11 +306,12 @@ object Terminal { } } private[sbt] lazy val formatEnabledInEnv: Boolean = logFormatEnabled.getOrElse(useColorDefault) + private[this] val isDumbTerminal = "dumb" == System.getenv("TERM") private[this] val hasConsole = Option(java.lang.System.console).isDefined private[this] def useColorDefault: Boolean = { // This approximates that both stdin and stdio are connected, // so by default color will be turned off for pipes and redirects. - props.map(_.color).orElse(isColorEnabledProp).getOrElse(hasConsole) + props.map(_.color).orElse(isColorEnabledProp).getOrElse(hasConsole && !isDumbTerminal) } private[this] lazy val isColorEnabledProp: Option[Boolean] = sys.props.get("sbt.color").orElse(sys.props.get("sbt.colour")).flatMap(parseLogOption) @@ -720,8 +721,7 @@ object Terminal { private[this] def newConsoleTerminal(): Terminal = { val system = JLine3.system - val in = if (System.console == null) nullWriteableInputStream else nonBlockingIn(system) - new ConsoleTerminal(in, originalOut, system) + new ConsoleTerminal(nonBlockingIn(system), originalOut, system) } private[sbt] def reset(): Unit = { @@ -743,6 +743,7 @@ object Terminal { case "jline.WindowsTerminal" => "windows" case "jline.AnsiWindowsTerminal" => "windows" case "jline.UnsupportedTerminal" => "none" + case null if isDumbTerminal => "none" case x => x } if (newValue != null) { @@ -784,7 +785,7 @@ object Terminal { val size = system.getSize (size.getColumns, size.getRows) } - override lazy val isAnsiSupported: Boolean = formatEnabledInEnv && !isCI + override lazy val isAnsiSupported: Boolean = !isDumbTerminal && formatEnabledInEnv && !isCI override private[sbt] def progressState: ProgressState = consoleProgressState.get override def isEchoEnabled: Boolean = try system.echo() @@ -811,9 +812,7 @@ object Terminal { override private[sbt] def setSize(width: Int, height: Int): Unit = system.setSize(new org.jline.terminal.Size(width, height)) - override def inputStream: InputStream = { - if (hasConsole) in else BlockingInputStream - } + override def inputStream: InputStream = in override private[sbt] def enterRawMode(): Unit = if (rawMode.compareAndSet(false, true) && hasConsole) { @@ -940,8 +939,6 @@ object Terminal { catch { case _: InterruptedException => } -1 } - private lazy val nullWriteableInputStream = - new WriteableInputStream(nullInputStream, "null-writeable-input-stream") private[sbt] class DefaultTerminal extends Terminal { override def close(): Unit = {} override private[sbt] def progressState: ProgressState = new ProgressState(1)