Clear prompt only if there are no bytes pending

When sbt is running a background process that logs to stdout, the output
can be inadvertently deleted before it has been printed. When the user
is in the prompt state and a log message comes in, we want to delete the
prompt before we print the log. The problem is println is often
implemented with a write of the content followed by a second write of
the system line separator. When that happened, we would print the
content and then immediately delete it when the newline came in. The fix
is to not clear the prompt if there are any bytes that have been written
without a newline, which was tracked by the currentLineBytes variable.
This commit is contained in:
Ethan Atkins 2020-09-25 10:32:58 -07:00
parent a79ef52f74
commit 9e0cd4cde6
1 changed files with 3 additions and 3 deletions

View File

@ -72,8 +72,7 @@ private[sbt] final class ProgressState(
if (!lines.endsWith(System.lineSeparator)) {
val allLines = lines.split(System.lineSeparator)
allLines.dropRight(1).foreach(appendLine)
allLines.lastOption
.foreach(currentLineBytes.get ++= _.getBytes("UTF-8"))
allLines.lastOption.foreach(currentLineBytes.get ++= _.getBytes("UTF-8"))
} else if (lines.contains(System.lineSeparator)) {
lines.split(System.lineSeparator).foreach(appendLine)
}
@ -92,11 +91,12 @@ private[sbt] final class ProgressState(
printStream: PrintStream,
hasProgress: Boolean
): Unit = {
val canClearPrompt = currentLineBytes.get.isEmpty
addBytes(terminal, bytes)
if (hasProgress) {
val toWrite = new ArrayBuffer[Byte]
terminal.prompt match {
case a: Prompt.AskUser if a.render.nonEmpty =>
case a: Prompt.AskUser if a.render.nonEmpty && canClearPrompt =>
toWrite ++= (DeleteLine + ClearScreenAfterCursor + CursorLeft1000).getBytes("UTF-8")
case _ =>
}