From 44ef71844869f7aa38df90132db8109cf11555fd Mon Sep 17 00:00:00 2001 From: Ethan Atkins Date: Tue, 17 Dec 2019 10:24:20 -0800 Subject: [PATCH] Improve run command warning When the user inputs `run` or `runMain` we shouldn't print the warning about multiple classes because in the case of run they already will be prompted to select the classes and in the case of runMain, they are already required to specify the class name. Bonus: * improve punctuation * add clear screen to selector dialogue * print selector dialogue in one call to println -- this should prevent the possibility of messages from other threads being interlaced with the dialogue --- main/src/main/scala/sbt/Defaults.scala | 24 +++++++++++++++----- run/src/main/scala/sbt/SelectMainClass.scala | 13 +++++++---- 2 files changed, 26 insertions(+), 11 deletions(-) diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index 9c13e176b..1872fb7e1 100755 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -716,7 +716,15 @@ object Defaults extends BuildCommon { forkOptions := forkOptionsTask.value, selectMainClass := mainClass.value orElse askForMainClass(discoveredMainClasses.value), mainClass in run := (selectMainClass in run).value, - mainClass := pickMainClassOrWarn(discoveredMainClasses.value, streams.value.log), + mainClass := { + val logWarning = state.value.currentCommand + .flatMap(_.commandLine.split(" ").headOption.map(_.trim)) + .fold(true) { + case "run" | "runMain" => false + case _ => true + } + pickMainClassOrWarn(discoveredMainClasses.value, streams.value.log, logWarning) + }, runMain := foregroundRunMainTask.evaluated, run := foregroundRunTask.evaluated, fgRun := runTask(fullClasspath, mainClass in run, runner in run).evaluated, @@ -1483,12 +1491,16 @@ object Defaults extends BuildCommon { def pickMainClass(classes: Seq[String]): Option[String] = sbt.SelectMainClass(None, classes) - private def pickMainClassOrWarn(classes: Seq[String], logger: Logger): Option[String] = { + private def pickMainClassOrWarn( + classes: Seq[String], + logger: Logger, + logWarning: Boolean + ): Option[String] = { classes match { - case multiple if multiple.size > 1 => - logger.warn( - "Multiple main classes detected. Run 'show discoveredMainClasses' to see the list" - ) + case multiple if multiple.size > 1 && logWarning => + val msg = + "Multiple main classes detected. Run 'show discoveredMainClasses' to see the list." + logger.warn(msg) case _ => } pickMainClass(classes) diff --git a/run/src/main/scala/sbt/SelectMainClass.scala b/run/src/main/scala/sbt/SelectMainClass.scala index 7de45e9ca..8fab6191f 100644 --- a/run/src/main/scala/sbt/SelectMainClass.scala +++ b/run/src/main/scala/sbt/SelectMainClass.scala @@ -7,6 +7,7 @@ package sbt +import sbt.internal.util.ConsoleAppender import sbt.internal.util.Util.{ AnyOps, none } object SelectMainClass { @@ -19,12 +20,14 @@ object SelectMainClass { case Nil => None case head :: Nil => Some(head) case multiple => - promptIfMultipleChoices flatMap { prompt => - println("\nMultiple main classes detected, select one to run:\n") - for ((className, index) <- multiple.zipWithIndex) - println(" [" + (index + 1) + "] " + className) + promptIfMultipleChoices.flatMap { prompt => + val header = "\nMultiple main classes detected. Select one to run:\n" + val classes = multiple.zipWithIndex + .map { case (className, index) => s" [${index + 1}] $className" } + .mkString("\n") + println(ConsoleAppender.clearScreen(0) + header + classes) + val line = trim(prompt("\nEnter number: ")) - println("") toInt(line, multiple.length) map multiple.apply } }