From 841b6dbfd843a8629bb6cfac54b88c8f87ee83a6 Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Fri, 7 Aug 2020 13:58:23 -0700 Subject: [PATCH] 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. --- .../src/main/scala/sbt/internal/util/Terminal.scala | 4 ++-- .../src/main/scala/sbt/BasicCommandStrings.scala | 1 - main-command/src/main/scala/sbt/State.scala | 7 ++----- main/src/main/scala/sbt/Main.scala | 9 +-------- main/src/main/scala/sbt/MainLoop.scala | 12 +++++------- main/src/main/scala/sbt/internal/Continuous.scala | 7 +++---- .../main/scala/sbt/internal/FastTrackCommands.scala | 3 +-- .../scala/sbt/internal/nio/CheckBuildSources.scala | 8 ++------ 8 files changed, 16 insertions(+), 35 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 e44573930..8b7a99df6 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 @@ -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 = diff --git a/main-command/src/main/scala/sbt/BasicCommandStrings.scala b/main-command/src/main/scala/sbt/BasicCommandStrings.scala index d00b756be..eef42b3cc 100644 --- a/main-command/src/main/scala/sbt/BasicCommandStrings.scala +++ b/main-command/src/main/scala/sbt/BasicCommandStrings.scala @@ -215,7 +215,6 @@ $AliasCommand name= def FailureWall: String = "resumeFromFailure" - def SetTerminal = "sbtSetTerminal" def ReportResult = "sbtReportResult" def CompleteExec = "sbtCompleteExec" def MapExec = "sbtMapExec" diff --git a/main-command/src/main/scala/sbt/State.scala b/main-command/src/main/scala/sbt/State.scala index a0d21b949..409bac887 100644 --- a/main-command/src/main/scala/sbt/State.scala +++ b/main-command/src/main/scala/sbt/State.scala @@ -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) } } diff --git a/main/src/main/scala/sbt/Main.scala b/main/src/main/scala/sbt/Main.scala index f3a93ee2f..61777b2ec 100644 --- a/main/src/main/scala/sbt/Main.scala +++ b/main/src/main/scala/sbt/Main.scala @@ -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() diff --git a/main/src/main/scala/sbt/MainLoop.scala b/main/src/main/scala/sbt/MainLoop.scala index 99256ed79..b1822aa31 100644 --- a/main/src/main/scala/sbt/MainLoop.scala +++ b/main/src/main/scala/sbt/MainLoop.scala @@ -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 { diff --git a/main/src/main/scala/sbt/internal/Continuous.scala b/main/src/main/scala/sbt/internal/Continuous.scala index 39420a1fa..80cf2206b 100644 --- a/main/src/main/scala/sbt/internal/Continuous.scala +++ b/main/src/main/scala/sbt/internal/Continuous.scala @@ -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 "; ") diff --git a/main/src/main/scala/sbt/internal/FastTrackCommands.scala b/main/src/main/scala/sbt/internal/FastTrackCommands.scala index 8c53f81de..13774fe7c 100644 --- a/main/src/main/scala/sbt/internal/FastTrackCommands.scala +++ b/main/src/main/scala/sbt/internal/FastTrackCommands.scala @@ -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), diff --git a/main/src/main/scala/sbt/internal/nio/CheckBuildSources.scala b/main/src/main/scala/sbt/internal/nio/CheckBuildSources.scala index 95e64d22b..57be28464 100644 --- a/main/src/main/scala/sbt/internal/nio/CheckBuildSources.scala +++ b/main/src/main/scala/sbt/internal/nio/CheckBuildSources.scala @@ -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)