From 1a2bfc546bbaab13e44cc421cb027a8f6228611a Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 7 Mar 2017 12:14:55 +0000 Subject: [PATCH 1/7] Notify & enable users to stay in the warm shell Notify & enable users to stay in sbt's shell on the warm JVM by hitting [ENTER] while sbt is running. Looks like this; first I run 'sbt about', then I hit [ENTER]: $ sbt about [info] !!! Executing in batch mode !!! For better performance, hit [ENTER] to remain in the sbt shell [info] Loading global plugins from /Users/dnw/.dotfiles/.sbt/0.13/plugins [info] Loading project definition from /s/t/project [info] Set current project to t (in build file:/s/t/) [info] This is sbt 0.13.14-SNAPSHOT [info] The current project is {file:/s/t/}t 0.1.0-SNAPSHOT [info] The current project is built against Scala 2.12.1 [info] Available Plugins: sbt.plugins.IvyPlugin, sbt.plugins.JvmPlugin, sbt.plugins.CorePlugin, sbt.plugins.JUnitXmlReportPlugin, sbt.plugins.Giter8TemplatePlugin [info] sbt, sbt plugins, and build definitions are using Scala 2.10.6 > > Fixes #2987 --- main-command/src/main/scala/sbt/State.scala | 13 ++++++++++++- main/src/main/scala/sbt/MainLoop.scala | 4 ++++ notes/0.13.14/stay-in-shell.md | 7 +++++++ 3 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 notes/0.13.14/stay-in-shell.md diff --git a/main-command/src/main/scala/sbt/State.scala b/main-command/src/main/scala/sbt/State.scala index 11d0de3eb..8141d6f52 100644 --- a/main-command/src/main/scala/sbt/State.scala +++ b/main-command/src/main/scala/sbt/State.scala @@ -196,7 +196,18 @@ object State { /** Provides operations and transformations on State. */ implicit def stateOps(s: State): StateOps = new StateOps { - def process(f: (Exec, State) => State): State = + def process(f: (Exec, State) => State): State = { + def doX(x: Exec, xs: List[Exec]) = { + log.debug(s"> $x") + f(x, s.copy(remainingCommands = xs, currentCommand = Some(x), history = x :: s.history)) + } + def isInteractive = System.console() != null + def hasInput = System.console().reader().ready() + s.remainingCommands match { + case List() => if (isInteractive && hasInput) doX(Exec("shell", s.source), Nil) else exit(true) + case List(x, xs @ _*) => doX(x, xs) + } + } s.remainingCommands match { case List() => exit(true) case x :: xs => diff --git a/main/src/main/scala/sbt/MainLoop.scala b/main/src/main/scala/sbt/MainLoop.scala index f269d571e..5b45055e1 100644 --- a/main/src/main/scala/sbt/MainLoop.scala +++ b/main/src/main/scala/sbt/MainLoop.scala @@ -72,6 +72,10 @@ object MainLoop { val newLogging = state.globalLogging.newAppender(full, out, logBacking) // transferLevels(state, newLogging) val loggedState = state.copy(globalLogging = newLogging) + def isInteractive = System.console() != null + def hasShell = state.remainingCommands contains "shell" + if (isInteractive && !hasShell) + state.log info "!!! Executing in batch mode !!! For better performance, hit [ENTER] to remain in the sbt shell" try run(loggedState) finally out.close() } diff --git a/notes/0.13.14/stay-in-shell.md b/notes/0.13.14/stay-in-shell.md new file mode 100644 index 000000000..be4c7f956 --- /dev/null +++ b/notes/0.13.14/stay-in-shell.md @@ -0,0 +1,7 @@ +### Improvements + +- Notifies & enables users to stay in sbt's shell on the warm JVM by hitting \[ENTER\] while sbt is running. [#2987][]/[#2996][] by [@dwijnand][] + +[#2987]: https://github.com/sbt/sbt/issues/2987 +[#2996]: https://github.com/sbt/sbt/pull/2996 +[@dwijnand]: https://github.com/dwijnand From f5d7c384a49e9d064b1dcc02ea3d0f9b68600d22 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 7 Mar 2017 13:01:44 +0000 Subject: [PATCH 2/7] Switch from log.info and !!! to log.warn Good idea, Lars. Thanks. --- main/src/main/scala/sbt/MainLoop.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/main/src/main/scala/sbt/MainLoop.scala b/main/src/main/scala/sbt/MainLoop.scala index 5b45055e1..e3c1c7142 100644 --- a/main/src/main/scala/sbt/MainLoop.scala +++ b/main/src/main/scala/sbt/MainLoop.scala @@ -75,7 +75,7 @@ object MainLoop { def isInteractive = System.console() != null def hasShell = state.remainingCommands contains "shell" if (isInteractive && !hasShell) - state.log info "!!! Executing in batch mode !!! For better performance, hit [ENTER] to remain in the sbt shell" + state.log warn "Executing in batch mode; for better performance, hit [ENTER] to remain in the sbt shell" try run(loggedState) finally out.close() } From 7b4a349d5bba5a9c156e1cbe441401b7e10df36b Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 7 Mar 2017 13:30:56 +0000 Subject: [PATCH 3/7] Instruct how to get into interactive mode directly --- main/src/main/scala/sbt/MainLoop.scala | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/main/src/main/scala/sbt/MainLoop.scala b/main/src/main/scala/sbt/MainLoop.scala index e3c1c7142..5c6735148 100644 --- a/main/src/main/scala/sbt/MainLoop.scala +++ b/main/src/main/scala/sbt/MainLoop.scala @@ -74,8 +74,10 @@ object MainLoop { val loggedState = state.copy(globalLogging = newLogging) def isInteractive = System.console() != null def hasShell = state.remainingCommands contains "shell" - if (isInteractive && !hasShell) - state.log warn "Executing in batch mode; for better performance, hit [ENTER] to remain in the sbt shell" + if (isInteractive && !hasShell) { + state.log warn "BATCH MODE: for better performance hit [ENTER] to switch to interactive mode" + state.log warn " consider launching sbt without any commands, or explicitly passing 'shell'" + } try run(loggedState) finally out.close() } From 6d3129dcb713c8e6a561787ee3523365f7d9e190 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Tue, 7 Mar 2017 13:56:05 +0000 Subject: [PATCH 4/7] Try communicating in actual English --- main/src/main/scala/sbt/MainLoop.scala | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/main/src/main/scala/sbt/MainLoop.scala b/main/src/main/scala/sbt/MainLoop.scala index 5c6735148..80d18c986 100644 --- a/main/src/main/scala/sbt/MainLoop.scala +++ b/main/src/main/scala/sbt/MainLoop.scala @@ -75,7 +75,8 @@ object MainLoop { def isInteractive = System.console() != null def hasShell = state.remainingCommands contains "shell" if (isInteractive && !hasShell) { - state.log warn "BATCH MODE: for better performance hit [ENTER] to switch to interactive mode" + state.log warn "Executing in batch mode." + state.log warn " For better performance, hit [ENTER] to switch to interactive mode, or" state.log warn " consider launching sbt without any commands, or explicitly passing 'shell'" } try run(loggedState) finally out.close() From c41d428dbcafe5e1a28c2ce6291998d334c1b857 Mon Sep 17 00:00:00 2001 From: Dale Wijnand Date: Mon, 13 Mar 2017 15:44:28 +0000 Subject: [PATCH 5/7] Handle non-shell sbt startup warning The sbt/sbt-launcher-package doesn't invoke sbt with the "shell" command. sbt has a mechanism for handling this in its "boot" command that adds an "iflast shell" to the commands. Handle this when displaying the "Executing in batch mode" warning. Fixes #3004 --- main/src/main/scala/sbt/MainLoop.scala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/main/src/main/scala/sbt/MainLoop.scala b/main/src/main/scala/sbt/MainLoop.scala index 80d18c986..a9b9edcf3 100644 --- a/main/src/main/scala/sbt/MainLoop.scala +++ b/main/src/main/scala/sbt/MainLoop.scala @@ -74,7 +74,12 @@ object MainLoop { val loggedState = state.copy(globalLogging = newLogging) def isInteractive = System.console() != null def hasShell = state.remainingCommands contains "shell" - if (isInteractive && !hasShell) { + /** + * The "boot" command adds "iflast shell" ("if last shell") + * which basically means it falls back to shell if there are no further commands + */ + def endsWithBoot = state.remainingCommands.lastOption exists (_ == "boot") + if (isInteractive && !hasShell && !endsWithBoot) { state.log warn "Executing in batch mode." state.log warn " For better performance, hit [ENTER] to switch to interactive mode, or" state.log warn " consider launching sbt without any commands, or explicitly passing 'shell'" From 7ffae0f7df333d9d5c4b2576193bf4ff424f6352 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Tue, 4 Apr 2017 19:59:25 -0400 Subject: [PATCH 6/7] Fix patch error --- main-command/src/main/scala/sbt/State.scala | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/main-command/src/main/scala/sbt/State.scala b/main-command/src/main/scala/sbt/State.scala index 8141d6f52..e76546533 100644 --- a/main-command/src/main/scala/sbt/State.scala +++ b/main-command/src/main/scala/sbt/State.scala @@ -205,16 +205,9 @@ object State { def hasInput = System.console().reader().ready() s.remainingCommands match { case List() => if (isInteractive && hasInput) doX(Exec("shell", s.source), Nil) else exit(true) - case List(x, xs @ _*) => doX(x, xs) + case List(x, xs @ _*) => doX(x, xs.toList) } } - s.remainingCommands match { - case List() => exit(true) - case x :: xs => - log.debug(s"> $x") - f(x, s.copy(remainingCommands = xs, currentCommand = Some(x), history = x :: s.history)) - } - def :::(newCommands: List[String]): State = ++:(newCommands map { Exec(_, s.source) }) def ++:(newCommands: List[Exec]): State = s.copy(remainingCommands = newCommands ::: s.remainingCommands) def ::(command: String): State = +:(Exec(command, s.source)) From 15255c15b0315ee265b194ee7b8ba1ad54abdb93 Mon Sep 17 00:00:00 2001 From: Eugene Yokota Date: Tue, 4 Apr 2017 20:00:56 -0400 Subject: [PATCH 7/7] Don't warn on server command --- main/src/main/scala/sbt/MainLoop.scala | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/main/src/main/scala/sbt/MainLoop.scala b/main/src/main/scala/sbt/MainLoop.scala index a9b9edcf3..d4be1d232 100644 --- a/main/src/main/scala/sbt/MainLoop.scala +++ b/main/src/main/scala/sbt/MainLoop.scala @@ -73,13 +73,14 @@ object MainLoop { // transferLevels(state, newLogging) val loggedState = state.copy(globalLogging = newLogging) def isInteractive = System.console() != null - def hasShell = state.remainingCommands contains "shell" + def hasCommand(cmd: String): Boolean = + (state.remainingCommands find { x => x.commandLine == cmd }).isDefined /** * The "boot" command adds "iflast shell" ("if last shell") * which basically means it falls back to shell if there are no further commands */ - def endsWithBoot = state.remainingCommands.lastOption exists (_ == "boot") - if (isInteractive && !hasShell && !endsWithBoot) { + def endsWithBoot = state.remainingCommands.lastOption exists (_.commandLine == "boot") + if (isInteractive && !hasCommand("shell") && !hasCommand("server") && !endsWithBoot) { state.log warn "Executing in batch mode." state.log warn " For better performance, hit [ENTER] to switch to interactive mode, or" state.log warn " consider launching sbt without any commands, or explicitly passing 'shell'"