Add reprompt fast track command

With the latest sbt snapshot, the ui would get stuck if the user entered
an empty command. They would be presented with an empty prompt and could
not input any commands. This was caused by the change in
d569abe70a that reset the prompt after a
line was read. I had tried to optimize line reading by ignoring empty
commands in UITask.readline so we wouldn't have to make a new thread.
This optimization wasn't really buying much since it only affects how
quickly the user is reprompted after entering an empty command. Unless a
user is spamming the <enter> key, they shouldn't notice a difference.
This commit is contained in:
Ethan Atkins 2020-08-10 11:02:02 -07:00
parent 31bea086aa
commit adc8d5ee6e
3 changed files with 9 additions and 8 deletions

View File

@ -74,13 +74,13 @@ object LineReader {
parser: Parser[_],
terminal: Terminal,
): LineReader = {
val term = JLine3(terminal)
// We may want to consider insourcing LineReader.java from jline. We don't otherwise
// directly need jline3 for sbt.
val reader = LineReaderBuilder.builder().terminal(term).completer(completer(parser)).build()
historyPath.foreach(f => reader.setVariable(JLineReader.HISTORY_FILE, f))
new LineReader {
override def readLine(prompt: String, mask: Option[Char]): Option[String] = {
val term = JLine3(terminal)
val reader = LineReaderBuilder.builder().terminal(term).completer(completer(parser)).build()
historyPath.foreach(f => reader.setVariable(JLineReader.HISTORY_FILE, f))
try terminal.withRawInput {
Option(mask.map(reader.readLine(prompt, _)).getOrElse(reader.readLine(prompt)))
} catch {

View File

@ -59,7 +59,7 @@ private[sbt] object UITask {
def readLine(): Either[String, String] =
try {
val clear = terminal.ansi(ClearPromptLine, "")
@tailrec def impl(): Either[String, String] = {
val res = {
val thread = Thread.currentThread
if (thread.isInterrupted || closed.get) throw interrupted
val reader = LineReader.createReader(history(state), parser, terminal)
@ -76,16 +76,17 @@ private[sbt] object UITask {
case None => Left(TerminateAction)
case Some(s: String) =>
s.trim() match {
case "" => impl()
// We need to put the empty string on the fast track queue so that we can
// reprompt the user if another command is running on the server.
case "" => Left("")
case cmd @ (`Shutdown` | `TerminateAction` | `Cancel`) => Left(cmd)
case cmd => Right(cmd)
}
}
}
val res = impl()
terminal.setPrompt(Prompt.Pending)
res
} catch { case e: InterruptedException => Right("") }
} catch { case e: InterruptedException => Left("") }
override def close(): Unit = closed.set(true)
}
}

View File

@ -446,7 +446,7 @@ private[sbt] final class CommandExchange {
case null =>
case mt: FastTrackTask =>
mt.task match {
case `attach` => mt.channel.prompt(ConsolePromptEvent(lastState.get))
case `attach` | "" => mt.channel.prompt(ConsolePromptEvent(lastState.get))
case `Cancel` =>
Option(currentExecRef.get).foreach(cancel)
mt.channel.prompt(ConsolePromptEvent(lastState.get))