Remove SetTerminal command

Rather than relying on a command, I realized it makes more sense to
explicitly set the terminal for the calling channel in MainLoop. By
doing it this way, we can also ensure that we always reset it to the
previous value.
This commit is contained in:
Ethan Atkins 2020-08-07 13:58:23 -07:00
parent 46724159da
commit 841b6dbfd8
8 changed files with 16 additions and 35 deletions

View File

@ -174,9 +174,9 @@ object Terminal {
try Terminal.console.printStream.println(s"[info] $string")
catch { case _: IOException => }
}
private[sbt] def set(terminal: Terminal) = {
activeTerminal.set(terminal)
private[sbt] def set(terminal: Terminal): Terminal = {
jline.TerminalFactory.set(terminal.toJLine)
activeTerminal.getAndSet(terminal)
}
implicit class TerminalOps(private val term: Terminal) extends AnyVal {
def ansi(richString: => String, string: => String): String =

View File

@ -215,7 +215,6 @@ $AliasCommand name=
def FailureWall: String = "resumeFromFailure"
def SetTerminal = "sbtSetTerminal"
def ReportResult = "sbtReportResult"
def CompleteExec = "sbtCompleteExec"
def MapExec = "sbtMapExec"

View File

@ -21,7 +21,6 @@ import BasicCommandStrings.{
MapExec,
PopOnFailure,
ReportResult,
SetTerminal,
StartServer,
StashOnFailure,
networkExecPrefix,
@ -314,10 +313,8 @@ object State {
val stash = Exec(StashOnFailure, None)
val failureWall = Exec(FailureWall, None)
val pop = Exec(PopOnFailure, None)
val setTerm = Exec(s"$SetTerminal ${s.channelName}", None)
val setConsole = Exec(s"$SetTerminal console0", None)
val remaining = stash :: map :: cmd :: complete :: failureWall :: pop :: setConsole :: report :: xs
runCmd(setTerm, remaining)
val remaining = map :: cmd :: complete :: failureWall :: pop :: report :: xs
runCmd(stash, remaining)
case _ => runCmd(x, xs)
}
}

View File

@ -15,7 +15,7 @@ import java.util.Properties
import java.util.concurrent.ForkJoinPool
import java.util.concurrent.atomic.AtomicBoolean
import sbt.BasicCommandStrings.{ SetTerminal, Shell, Shutdown, TemplateCommand, networkExecPrefix }
import sbt.BasicCommandStrings.{ Shell, Shutdown, TemplateCommand, networkExecPrefix }
import sbt.Project.LoadAction
import sbt.compiler.EvalImports
import sbt.internal.Aggregation.AnyKeys
@ -311,7 +311,6 @@ object BuiltinCommands {
NetworkChannel.disconnect,
waitCmd,
promptChannel,
setTerminalCommand,
) ++ allBasicCommands ++ ContinuousCommands.value
def DefaultBootCommands: Seq[String] =
@ -960,12 +959,6 @@ object BuiltinCommands {
Command.command(ClearCaches, help)(f)
}
def setTerminalCommand = Command.arb(_ => BasicCommands.reportParser(SetTerminal)) {
(s, channel) =>
StandardMain.exchange.channelForName(channel).foreach(c => Terminal.set(c.terminal))
s
}
private[sbt] def waitCmd: Command =
Command.arb(
_ => ContinuousCommands.waitWatch.examples() ~> " ".examples() ~> matched(any.*).examples()

View File

@ -10,7 +10,7 @@ package sbt
import java.io.PrintWriter
import java.util.Properties
import sbt.BasicCommandStrings.{ SetTerminal, StashOnFailure, networkExecPrefix }
import sbt.BasicCommandStrings.{ StashOnFailure, networkExecPrefix }
import sbt.internal.ShutdownHooks
import sbt.internal.langserver.ErrorCodes
import sbt.internal.protocol.JsonRpcResponseError
@ -202,6 +202,8 @@ object MainLoop {
StandardMain.exchange.setState(progressState)
StandardMain.exchange.setExec(Some(exec))
StandardMain.exchange.unprompt(ConsoleUnpromptEvent(exec.source))
val terminal = channelName.flatMap(exchange.channelForName(_).map(_.terminal))
val prevTerminal = terminal.map(Terminal.set)
/*
* FastTrackCommands.evaluate can be significantly faster than Command.process because
* it avoids an expensive parsing step for internal commands that are easy to parse.
@ -212,8 +214,8 @@ object MainLoop {
Command.process(exec.commandLine, progressState)
// Flush the terminal output after command evaluation to ensure that all output
// is displayed in the thin client before we report the command status.
val terminal = channelName.flatMap(exchange.channelForName(_).map(_.terminal))
terminal.foreach(_.flush())
prevTerminal.foreach(Terminal.set)
if (exec.execId.fold(true)(!_.startsWith(networkExecPrefix)) &&
!exec.commandLine.startsWith(networkExecPrefix)) {
val doneEvent = ExecStatusEvent(
@ -232,11 +234,7 @@ object MainLoop {
state.get(CheckBuildSourcesKey) match {
case Some(cbs) =>
if (!cbs.needsReload(state, exec)) process()
else {
val isSetTerminal = exec.commandLine.startsWith(SetTerminal)
if (isSetTerminal) exec +: Exec("reload", None) +: state.remove(CheckBuildSourcesKey)
else Exec("reload", None) +: exec +: state.remove(CheckBuildSourcesKey)
}
else Exec("reload", None) +: exec +: state.remove(CheckBuildSourcesKey)
case _ => process()
}
} catch {

View File

@ -1210,9 +1210,8 @@ private[sbt] object ContinuousCommands {
state.get(watchStates).flatMap(_.get(channel)) match {
case None => state
case Some(cs) =>
val pre = StashOnFailure :: s"$SetTerminal $channel" :: s"$preWatch $channel" :: Nil
val post = FailureWall :: PopOnFailure :: s"$SetTerminal ${ConsoleChannel.defaultName}" ::
s"$postWatch $channel" :: s"$waitWatch $channel" :: Nil
val pre = StashOnFailure :: s"$preWatch $channel" :: Nil
val post = FailureWall :: PopOnFailure :: s"$postWatch $channel" :: s"$waitWatch $channel" :: Nil
pre ::: cs.commands.toList ::: post ::: state
}
}
@ -1251,7 +1250,7 @@ private[sbt] object ContinuousCommands {
case Watch.Trigger => Right(s"$runWatch ${channel.name}")
case Watch.Reload =>
val rewatch = s"$ContinuousExecutePrefix ${ws.count} ${cs.commands mkString "; "}"
stop.map(_ :: s"$SetTerminal ${channel.name}" :: "reload" :: rewatch :: Nil mkString "; ")
stop.map(_ :: "reload" :: rewatch :: Nil mkString "; ")
case Watch.Prompt => stop.map(_ :: s"$PromptChannel ${channel.name}" :: Nil mkString ";")
case Watch.Run(commands) =>
stop.map(_ +: commands.map(_.commandLine).filter(_.nonEmpty) mkString "; ")

View File

@ -10,7 +10,7 @@ package internal
import BasicCommandStrings._
import BasicCommands._
import BuiltinCommands.{ setTerminalCommand, shell, waitCmd }
import BuiltinCommands.{ shell, waitCmd }
import ContinuousCommands._
import sbt.internal.util.complete.Parser
@ -32,7 +32,6 @@ private[sbt] object FastTrackCommands {
StashOnFailure -> fromCommand(StashOnFailure, stashOnFailure, arguments = false),
PopOnFailure -> fromCommand(PopOnFailure, popOnFailure, arguments = false),
Shell -> fromCommand(Shell, shell),
SetTerminal -> fromCommand(SetTerminal, setTerminalCommand),
failWatch -> fromCommand(failWatch, failWatchCommand),
preWatch -> fromCommand(preWatch, preWatchCommand),
postWatch -> fromCommand(postWatch, postWatchCommand),

View File

@ -10,7 +10,7 @@ package internal.nio
import java.nio.file.Path
import java.util.concurrent.atomic.{ AtomicBoolean, AtomicReference }
import sbt.BasicCommandStrings.{ RebootCommand, SetTerminal, Shutdown, TerminateAction }
import sbt.BasicCommandStrings.{ RebootCommand, Shutdown, TerminateAction }
import sbt.Keys.{ baseDirectory, pollInterval, state }
import sbt.Scope.Global
import sbt.SlashSyntax0._
@ -108,11 +108,7 @@ private[sbt] class CheckBuildSources extends AutoCloseable {
state: State,
exec: Exec
): Boolean = {
val isSetTerminal = exec.commandLine.startsWith(SetTerminal)
val name =
if (isSetTerminal)
exec.commandLine.split(s"$SetTerminal ").lastOption.filterNot(_.isEmpty)
else exec.source.map(_.channelName)
val name = exec.source.map(_.channelName)
val loggerOrTerminal =
name.flatMap(StandardMain.exchange.channelForName(_).map(_.terminal)) match {
case Some(t) => Right(t)