From 825d0bad6ab4192a4900f13a626d865e98f1065f Mon Sep 17 00:00:00 2001 From: Katherine Prevost Date: Mon, 29 Jun 2020 16:38:49 -0400 Subject: [PATCH] Added --repl and --no-server and changed behavior of -i/--interactive to clarify command-line options. (#927) Pull request: https://github.com/lihaoyi/mill/pull/927 --- build.sc | 4 +- docs/pages/1 - Intro to Mill.md | 16 ++++---- docs/pages/2 - Configuring Mill.md | 9 +++-- main/src/MillMain.scala | 60 ++++++++++++++++++++++-------- 4 files changed, 62 insertions(+), 27 deletions(-) diff --git a/build.sc b/build.sc index f6d6895a87b..3bdf10f8ec2 100755 --- a/build.sc +++ b/build.sc @@ -597,7 +597,7 @@ def launcherScript(shellJvmArgs: Seq[String], | COURSIER_CACHE=.coursier ${java("mill.MillMain")} |else | case "$$1" in - | -i | --interactive ) + | -i | --interactive | --repl | --no-server ) | ${java("mill.MillMain")} | ;; | *) @@ -616,6 +616,8 @@ def launcherScript(shellJvmArgs: Seq[String], |if not "%JAVA_HOME%"=="" set "JAVACMD=%JAVA_HOME%\\bin\\java.exe" |if "%1" == "-i" set _I_=true |if "%1" == "--interactive" set _I_=true + |if "%1" == "--repl" set _I_=true + |if "%1" == "--no-server" set _I_=true |if defined _I_ ( | ${java("mill.MillMain")} |) else ( diff --git a/docs/pages/1 - Intro to Mill.md b/docs/pages/1 - Intro to Mill.md index 6271c9cade0..5a68b9fe8c5 100644 --- a/docs/pages/1 - Intro to Mill.md +++ b/docs/pages/1 - Intro to Mill.md @@ -65,7 +65,9 @@ Mill also works on a sh environment on Windows (e.g., [WSL](https://docs.microsoft.com/en-us/windows/wsl); to get started, follow the instructions in the [manual](#manual) section below. Note that: -* In some environments (such as WSL), mill might have to be run using interactive mode (`-i`) +* In some environments (such as WSL), mill might have to be run + without a server (using `-i`, `--interactive`, `--no-server`, or + `--repl`.) * On Cygwin, run the following after downloading mill: @@ -707,10 +709,10 @@ generate an IntelliJ project config for your build. This also configures IntelliJ to allow easy navigate & code-completion within your build file itself. -## The Build Repl +## The Build REPL ```bash -$ mill -i +$ mill --repl Loading... @ foo res0: foo.type = ammonite.predef.build#foo:4 @@ -747,10 +749,10 @@ res2: mill.scalalib.api.CompilationResult = CompilationResult( ) ``` -You can run `mill -i` to open a build REPL; this is a Scala console with your -`build.sc` loaded, which lets you run tasks interactively. The task-running -syntax is slightly different from the command-line, but more in-line with how -you would depend on tasks from within your build file. +You can run `mill --repl` to open a build REPL; this is a Scala console with +your `build.sc` loaded, which lets you run tasks interactively. The +task-running syntax is slightly different from the command-line, but more +in-line with how you would depend on tasks from within your build file. You can use this REPL to interactively explore your build to see what is available. diff --git a/docs/pages/2 - Configuring Mill.md b/docs/pages/2 - Configuring Mill.md index 9fc7754c85c..082c0aa9f3d 100644 --- a/docs/pages/2 - Configuring Mill.md +++ b/docs/pages/2 - Configuring Mill.md @@ -297,10 +297,11 @@ the same testing framework, etc. and all that can be extracted out into the Mill builds on ammonite which allows you to [define global configuration](http://ammonite.io/#ScriptPredef). Depending on -how you start mill 2 different files will be loaded. For interactive mode it's -`~/.mill/ammonite/predef.sc` and from the command line it's -`~/.mill/ammonite/predefScript.sc`. You might want to create a symlink from one -to the other to avoid duplication. +how you start mill, one of two files will be loaded. For the build REPL +(`--repl` or `-i` without specifying a target), `~/.mill/ammonite/predef.sc` +will be loaded, and for builds from the command line the file +`~/.mill/ammonite/predefScript.sc` will be included. You might want to create +a symlink from one to the other to avoid duplication. Example `~/.mill/ammonite/predef.sc` ```scala diff --git a/main/src/MillMain.scala b/main/src/MillMain.scala index 9644150619b..1aaf6c8a58d 100644 --- a/main/src/MillMain.scala +++ b/main/src/MillMain.scala @@ -13,13 +13,8 @@ import mill.api.DummyInputStream object MillMain { def main(args: Array[String]): Unit = { - // Remove the trailing interactive parameter, we already handled it on call site - val as = args match { - case Array(s, _*) if s == "-i" || s == "--interactive" => args.tail - case _ => args - } val (result, _) = main0( - as, + args, None, ammonite.Main.isInteractive(), System.in, @@ -49,11 +44,32 @@ object MillMain { val removed = Set("predef-code", "no-home-predef") + var repl = false + val replSignature = Arg[Config, Unit]( + "repl", None, + "Run Mill in interactive mode and start a build REPL. In this mode, no mill server will be used. Must be the first argument.", + (c, v) => { + repl = true + c + } + ) + + var noServer = false + val noServerSignature = Arg[Config, Unit]( + "no-server", None, + "Run Mill in interactive mode, suitable for opening REPLs and taking user input. In this mode, no mill server will be used. Must be the first argument.", + (c, v) => { + noServer = true + c + } + ) + var interactive = false val interactiveSignature = Arg[Config, Unit]( "interactive", Some('i'), - "Run Mill in interactive mode, suitable for opening REPLs and taking user input. In this mode, no mill server will be used.", + "Run Mill in interactive mode, suitable for opening REPLs and taking user input. In this mode, no mill server will be used. Must be the first argument.", (c, v) => { + // check for stdin == DummyInputStream, which means this wasn't handled interactive = true c } @@ -134,6 +150,8 @@ object MillMain { val millArgSignature = Cli.genericSignature.filter(a => !removed(a.name)) ++ Seq( + replSignature, + noServerSignature, interactiveSignature, showVersionSignature, disableTickerSignature, @@ -149,10 +167,14 @@ object MillMain { millArgSignature, Cli.Config(home = millHome, remoteLogging = false) ) match { - case _ if interactive => + case _ if (interactive || repl || noServer) + && stdin == DummyInputStream => // because this parameter was handled earlier (when in first position), // here it is too late and we can't handle it properly. - stderr.println("-i/--interactive must be passed in as the first argument") + stderr.println("-i/--interactive/--repl/--no-server must be passed in as the first argument") + (false, None) + case _ if Seq(interactive, repl, noServer).count(identity) > 1 => + stderr.println("Only one of -i/--interactive, --repl, or --no-server may be given") (false, None) case Left(msg) => stderr.println(msg) @@ -177,16 +199,24 @@ object MillMain { (true, None) case Right((cliConfig, leftoverArgs)) => - - val repl = leftoverArgs.isEmpty - if (repl && stdin == DummyInputStream) { - stderr.println("Build repl needs to be run with the -i/--interactive flag") + val useRepl = repl || (interactive && leftoverArgs.isEmpty) + if ( repl && leftoverArgs.nonEmpty ) { + stderr.println("No target may be provided with the --repl flag") + (false, stateCache) + } else if ( leftoverArgs.isEmpty && noServer ) { + stderr.println("A target must be provided when not starting a build REPL") + (false, stateCache) + } else if ( useRepl && stdin == DummyInputStream ) { + stderr.println("Build REPL needs to be run with the -i/--interactive/--repl flag") (false, stateCache) }else{ + if ( useRepl && interactive ) { + stderr.println("WARNING: Starting a build REPL without --repl is deprecated") + } val systemProps = initialSystemProperties ++ extraSystemProperties val config = - if(!repl) cliConfig + if(!useRepl) cliConfig else cliConfig.copy( predefCode = s"""import $$file.build, build._ @@ -232,7 +262,7 @@ object MillMain { } } - if (repl) { + if (useRepl) { runner.printInfo("Loading...") (runner.watchLoop(isRepl = true, printing = false, _.run()), runner.stateCache) } else {