Add welcome banner to sbt shell

We want to notify users about the new features available in sbt 1.3.0 to
increase visibility. Turbo mode especially can benefit many builds, but
we have opted to leave it off by default for now.

The banner will be displayed the first time sbt enters the shell command
on each sbt run. The banner can be disabled globally with the sbt.banner
system property. It can be displayed on a per sbt version by running the
skipWelcomeBanner command. That command touches a file in the ~/.sbt/1.0
directory to make it persistent across all projects.
This commit is contained in:
Ethan Atkins 2019-06-08 12:19:26 -07:00
parent 47cd001eea
commit 5e0b9a0c2f
3 changed files with 58 additions and 1 deletions

View File

@ -9,6 +9,7 @@ package sbt
import java.io.{ File, IOException }
import java.net.URI
import java.nio.file.{ FileAlreadyExistsException, Files }
import java.util.concurrent.ForkJoinPool
import java.util.concurrent.atomic.AtomicBoolean
import java.util.{ Locale, Properties }
@ -214,6 +215,7 @@ object BuiltinCommands {
plugins,
addPluginSbtFile,
writeSbtVersion,
skipBanner,
notifyUsersAboutShell,
shell,
startServer,
@ -862,7 +864,8 @@ object BuiltinCommands {
def shell: Command = Command.command(Shell, Help.more(Shell, ShellDetailed)) { s0 =>
import sbt.internal.{ ConsolePromptEvent, ConsoleUnpromptEvent }
val exchange = StandardMain.exchange
val s1 = exchange run s0
val welcomeState = displayWelcomeBanner(s0)
val s1 = exchange run welcomeState
exchange publishEventMessage ConsolePromptEvent(s0)
val minGCInterval = Project
.extract(s1)
@ -943,4 +946,35 @@ object BuiltinCommands {
Command.command(NotifyUsersAboutShell) { state =>
notifyUsersAboutShell(state); state
}
private[this] def skipWelcomeFile(state: State, version: String) = {
val base = BuildPaths.getGlobalBase(state).toPath
base.resolve("preferences").resolve(version).resolve(SkipBannerFileName)
}
private def displayWelcomeBanner(state: State): State = {
if (!state.get(bannerHasBeenShown).getOrElse(false)) {
try {
val version = sbtVersion(state)
val skipFile = skipWelcomeFile(state, version)
Files.createDirectories(skipFile.getParent)
val suppress = !SysProp.banner || Files.exists(skipFile)
if (!suppress) state.log.info(Banner(version))
} catch { case _: IOException => /* Don't let errors in this command prevent startup */ }
state.put(bannerHasBeenShown, true)
} else state
}
private[this] val bannerHasBeenShown =
AttributeKey[Boolean]("banner-has-been-shown", Int.MaxValue)
private[this] val SkipBannerFileName = "skip-banner"
private[this] val SkipBanner = "skipBanner"
private[this] def skipBanner: Command = Command.command(SkipBanner)(skipBanner)
private def skipBanner(state: State): State = {
val skipFile = skipWelcomeFile(state, sbtVersion(state))
try Files.createFile(skipFile)
catch {
case _: FileAlreadyExistsException =>
case e: IOException => state.log.error(s"Couldn't create file $skipFile: $e")
}
state
}
}

View File

@ -0,0 +1,21 @@
/*
* sbt
* Copyright 2011 - 2018, Lightbend, Inc.
* Copyright 2008 - 2010, Mark Harrah
* Licensed under Apache License 2.0 (see LICENSE)
*/
package sbt.internal
private[sbt] object Banner {
def apply(version: String): String =
s"""
|Welcome to sbt $version.
|Here are some highlights of this release:
| - Coursier: new default library management using https://get-coursier.io
| - Super shell: displays actively running tasks
| - Turbo mode: makes `test` and `run` faster in interactive sessions. Try it by running `set ThisBuild / turbo := true`.
|See https://www.lightbend.com/blog/sbt-1.3.0-release for full release notes.
|Hide the banner for this release by running `skipBanner`.
|""".stripMargin.linesIterator.filter(_.nonEmpty).mkString("\n")
}

View File

@ -93,6 +93,8 @@ object SysProp {
coursierOpt.orElse(notIvyOpt).getOrElse(true)
}
def banner: Boolean = getOrTrue("sbt.banner")
def turbo: Boolean = getOrFalse("sbt.turbo")
def taskTimings: Boolean = getOrFalse("sbt.task.timings")