Skip to content

Commit c5e3d09

Browse files
committed
Suggest global interactive mode the first time --interactive is passed
1 parent 3315c66 commit c5e3d09

File tree

4 files changed

+67
-13
lines changed

4 files changed

+67
-13
lines changed

modules/cli/src/main/scala/scala/cli/commands/util/SharedOptionsUtil.scala

Lines changed: 45 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import scala.build._
1313
import scala.build.blooprifle.BloopRifleConfig
1414
import scala.build.compiler.{BloopCompilerMaker, ScalaCompilerMaker, SimpleScalaCompilerMaker}
1515
import scala.build.errors.BuildException
16+
import scala.build.interactive.Interactive
17+
import scala.build.interactive.Interactive.{InteractiveAsk, InteractiveNop}
1618
import scala.build.internal.CsLoggerUtil._
1719
import scala.build.internal.{Constants, FetchExternalBinary, OsLibc, Util}
1820
import scala.build.options.{Platform, ScalacOpt, ShadowingSeq}
@@ -25,7 +27,7 @@ import scala.concurrent.duration._
2527
import scala.util.Properties
2628
import scala.util.control.NonFatal
2729

28-
object SharedOptionsUtil {
30+
object SharedOptionsUtil extends CommandHelpers {
2931

3032
private def downloadInputs(cache: FileCache[Task]): String => Either[String, Array[Byte]] = {
3133
url =>
@@ -213,22 +215,56 @@ object SharedOptionsUtil {
213215
localRepository = LocalRepo.localRepo(directories.directories.localRepoDir),
214216
verbosity = Some(logging.verbosity),
215217
strictBloopJsonCheck = strictBloopJsonCheck,
216-
interactive = Some(interactiveMode)
218+
interactive = Some(() => interactive)
217219
),
218220
notForBloopOptions = bo.PostBuildOptions(
219221
scalaJsLinkerOptions = linkerOptions(js)
220222
)
221223
)
222224
}
223225

224-
def interactiveMode: Boolean = logging.verbosityOptions.interactive
225-
.orElse(configDb.get(Keys.interactive).getOrElse(None))
226-
.getOrElse(false)
226+
def globalInteractiveWasSuggested: Option[Boolean] =
227+
configDb.getOrNone(Keys.globalInteractiveWasSuggested, logger)
227228

228-
def configDb: ConfigDb =
229-
ConfigDb.open(v) match
230-
case Left(ex) => logger.exit(ex)
231-
case Right(configDb) => configDb
229+
def interactive: Interactive =
230+
(
231+
logging.verbosityOptions.interactive,
232+
configDb.getOrNone(Keys.interactive, logger),
233+
globalInteractiveWasSuggested
234+
) match {
235+
case (Some(true), _, Some(true)) => InteractiveAsk
236+
case (_, Some(true), _) => InteractiveAsk
237+
case (Some(true), _, _) =>
238+
val answers @ List(yesAnswer, _) = List("Yes", "No")
239+
InteractiveAsk.chooseOne(
240+
"""You have run the current scala-cli command with the --interactive mode turned on.
241+
|Would you like to leave it on permanently?""".stripMargin,
242+
answers
243+
) match {
244+
case Some(answer) if answer == yesAnswer =>
245+
configDb
246+
.set(Keys.interactive, true)
247+
.set(Keys.globalInteractiveWasSuggested, true)
248+
.save(v.directories.directories)
249+
logger.message(
250+
"--interactive is now set permanently. All future scala-cli commands will run with the flag set to true."
251+
)
252+
logger.message(
253+
"If you want to turn this setting off at any point, just run `scala-cli config interactive false`."
254+
)
255+
case _ =>
256+
configDb
257+
.set(Keys.globalInteractiveWasSuggested, true)
258+
.save(v.directories.directories)
259+
logger.message(
260+
"If you want to turn this setting permanently on at any point, just run `scala-cli config interactive true`."
261+
)
262+
}
263+
InteractiveAsk
264+
case _ => InteractiveNop
265+
}
266+
267+
def configDb: ConfigDb = ConfigDb.open(v).orExit(logger)
232268

233269
def downloadJvm(jvmId: String, options: bo.BuildOptions): String = {
234270
implicit val ec = options.finalCache.ec

modules/cli/src/main/scala/scala/cli/config/ConfigDb.scala

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ import com.github.plokhotnyuk.jsoniter_scala.macros._
55
import coursier.parse.RawJson
66

77
import java.nio.file.attribute.PosixFilePermission
8-
9-
import scala.build.Directories
8+
import scala.build.{Directories, Logger}
109
import scala.build.errors.BuildException
1110
import scala.cli.commands.SharedOptions
1211
import scala.cli.commands.util.CommonOps.SharedDirectoriesOptionsOps
@@ -44,6 +43,19 @@ final class ConfigDb private (
4443
.map(Some(_))
4544
}
4645

46+
/** Gets an entry.
47+
*
48+
* If the value cannot be decoded or the key isn't in the DB, None is returned.
49+
*
50+
* Otherwise, the value is returned wrapped in Some.
51+
*/
52+
def getOrNone[T](key: Key[T], logger: Logger): Option[T] = get[T](key) match {
53+
case Right(maybeValue) => maybeValue
54+
case Left(ex) =>
55+
logger.debug(ex)
56+
None
57+
}
58+
4759
/** Sets an entry in memory */
4860
def set[T](key: Key[T], value: T): this.type = {
4961
val b = key.write(value)

modules/cli/src/main/scala/scala/cli/config/Keys.scala

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,12 @@ object Keys {
1919

2020
val interactive = new Key.BooleanEntry(Seq.empty, "interactive")
2121

22-
def all = Seq[Key[_]](
22+
// setting indicating if the global interactive mode was suggested
23+
val globalInteractiveWasSuggested = new Key.BooleanEntry(Seq.empty, "interactive-was-suggested")
24+
25+
def all: Seq[Key[_]] = Seq[Key[_]](
2326
interactive,
27+
globalInteractiveWasSuggested,
2428
actions,
2529
userName,
2630
userEmail,

modules/options/src/main/scala/scala/build/options/InternalOptions.scala

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import coursier.cache.FileCache
44
import coursier.util.Task
55

66
import scala.build.Positioned
7+
import scala.build.interactive.Interactive
8+
import scala.build.interactive.Interactive.InteractiveNop
79

810
final case class InternalOptions(
911
keepDiagnostics: Boolean = false,
@@ -12,7 +14,7 @@ final case class InternalOptions(
1214
verbosity: Option[Int] = None,
1315
// FIXME Should be removed, not a real option (not meant to be set from using directives)
1416
strictBloopJsonCheck: Option[Boolean] = None,
15-
interactive: Option[Boolean] = None,
17+
interactive: Option[() => Interactive] = None,
1618
javaClassNameVersionOpt: Option[String] = None,
1719
/** Whether to keep the coursier.Resolution instance in [[scala.build.Artifacts]]
1820
*

0 commit comments

Comments
 (0)