diff --git a/main-command/src/main/scala/sbt/internal/ui/UserThread.scala b/main-command/src/main/scala/sbt/internal/ui/UserThread.scala index c547994b9..94f239bc0 100644 --- a/main-command/src/main/scala/sbt/internal/ui/UserThread.scala +++ b/main-command/src/main/scala/sbt/internal/ui/UserThread.scala @@ -31,31 +31,33 @@ private[sbt] class UserThread(val channel: CommandChannel) extends AutoCloseable private[sbt] def reset(state: State): Unit = if (!isClosed.get) { uiThread.synchronized { val task = channel.makeUIThread(state) - def submit(): Thread = { + def submit(): Unit = { val thread: Thread = new Thread(s"sbt-$name-ui-thread") { setDaemon(true) override def run(): Unit = try task.run() - finally uiThread.get match { - case (_, t) if t == this => uiThread.set(null) - case _ => + finally { + uiThread.getAndSet(null) match { + case prev @ (_, th) if th != this => uiThread.set(prev) + case _ => + } } } uiThread.getAndSet((task, thread)) match { case null => thread.start() - case (task, t) if t.getClass != task.getClass => - stopThreadImpl() + case (prevTask, prevThread) if prevTask.getClass != task.getClass => + prevTask.close() + prevThread.joinFor(1.second) thread.start() case t => uiThread.set(t) } - thread } uiThread.get match { - case null => uiThread.set((task, submit())) - case (t, _) if t.getClass == task.getClass => + case null => submit() + case (prevTask, _) if prevTask.getClass == task.getClass => case (t, thread) => stopThreadImpl() - uiThread.set((task, submit())) + submit() } } Option(lastProgressEvent.get).foreach(onProgressEvent) diff --git a/main/src/main/scala/sbt/Main.scala b/main/src/main/scala/sbt/Main.scala index 1f5888c78..61c8cc222 100644 --- a/main/src/main/scala/sbt/Main.scala +++ b/main/src/main/scala/sbt/Main.scala @@ -992,12 +992,19 @@ object BuiltinCommands { val exchange = StandardMain.exchange exchange.channelForName(channel) match { case Some(c) if ContinuousCommands.isInWatch(s0, c) => - c.prompt(ConsolePromptEvent(s0)) + if (c.terminal.prompt != Prompt.Watch) { + c.terminal.setPrompt(Prompt.Watch) + c.prompt(ConsolePromptEvent(s0)) + } else if (c.terminal.isSupershellEnabled) { + c.terminal.printStream.print(ConsoleAppender.ClearScreenAfterCursor) + c.terminal.printStream.flush() + } + val s1 = exchange.run(s0) val exec: Exec = getExec(s1, Duration.Inf) val remaining: List[Exec] = - Exec(s"${ContinuousCommands.waitWatch} $channel", None) :: - Exec(FailureWall, None) :: s1.remainingCommands + Exec(FailureWall, None) :: Exec(s"${ContinuousCommands.waitWatch} $channel", None) :: + s1.remainingCommands val newState = s1.copy(remainingCommands = exec +: remaining) if (exec.commandLine.trim.isEmpty) newState else newState.clearGlobalLog diff --git a/main/src/main/scala/sbt/MainLoop.scala b/main/src/main/scala/sbt/MainLoop.scala index 00205d251..1943bc083 100644 --- a/main/src/main/scala/sbt/MainLoop.scala +++ b/main/src/main/scala/sbt/MainLoop.scala @@ -226,9 +226,8 @@ object MainLoop { // temporarily set the prompt to running during task evaluation c.terminal.setPrompt(Prompt.Running) (() => { - c.terminal.setPrompt(prevPrompt) + if (c.terminal.prompt != Prompt.Watch) c.terminal.setPrompt(prevPrompt) ITerminal.set(prevTerminal) - c.terminal.setPrompt(prevPrompt) c.terminal.flush() }) -> progressState.put(Keys.terminalKey, Terminal(c.terminal)) case _ => (() => ()) -> progressState.put(Keys.terminalKey, Terminal(ITerminal.get)) diff --git a/main/src/main/scala/sbt/internal/Continuous.scala b/main/src/main/scala/sbt/internal/Continuous.scala index b416446f7..c5ba2aec9 100644 --- a/main/src/main/scala/sbt/internal/Continuous.scala +++ b/main/src/main/scala/sbt/internal/Continuous.scala @@ -1344,8 +1344,7 @@ private[sbt] object ContinuousCommands { private[sbt] val postWatchCommand = watchCommand(postWatch) { (channel, state) => val cs = watchState(state, channel) StandardMain.exchange.channelForName(channel).foreach { c => - c.terminal.setPrompt(Prompt.Watch) - c.unprompt(ConsoleUnpromptEvent(Some(CommandSource(channel)))) + c.terminal.setPrompt(Prompt.Pending) } val postState = state.get(watchStates) match { case None => state @@ -1360,7 +1359,10 @@ private[sbt] object ContinuousCommands { cs.callbacks.onExit() StandardMain.exchange .channelForName(channel) - .foreach(_.unprompt(ConsoleUnpromptEvent(Some(CommandSource(channel))))) + .foreach { c => + c.terminal.setPrompt(Prompt.Pending) + c.unprompt(ConsoleUnpromptEvent(Some(CommandSource(channel)))) + } afterWatchState.get(watchStates) match { case None => afterWatchState case Some(w) => afterWatchState.put(watchStates, w - channel)