From 1003de1b852e027e0caf250fbb8f4c74bdfea1a0 Mon Sep 17 00:00:00 2001 From: zetashift Date: Fri, 9 Jun 2023 23:24:18 +0200 Subject: [PATCH 01/13] Initial support for new command Adds a new command to scala-cli to enable creating projects through giter8 --- build.sc | 1 + .../scala/scala/cli/ScalaCliCommands.scala | 1 + .../scala/scala/cli/commands/new/New.scala | 18 +++++++++++++ .../scala/cli/commands/new/NewOptions.scala | 25 +++++++++++++++++++ project/deps.sc | 1 + 5 files changed, 46 insertions(+) create mode 100644 modules/cli/src/main/scala/scala/cli/commands/new/New.scala create mode 100644 modules/cli/src/main/scala/scala/cli/commands/new/NewOptions.scala diff --git a/build.sc b/build.sc index a19eb4fece..1c915c9beb 100644 --- a/build.sc +++ b/build.sc @@ -781,6 +781,7 @@ trait Cli extends SbtModule with ProtoBuildModule with CliLaunchers Deps.coursierLauncher, Deps.coursierProxySetup, Deps.coursierPublish.exclude((organization, "config_2.13")), + Deps.giter8, Deps.jimfs, // scalaJsEnvNodeJs pulls jimfs:1.1, whose class path seems borked (bin compat issue with the guava version it depends on) Deps.jniUtils, Deps.jsoniterCore, diff --git a/modules/cli/src/main/scala/scala/cli/ScalaCliCommands.scala b/modules/cli/src/main/scala/scala/cli/ScalaCliCommands.scala index 53ea8167b4..c5c05f3802 100644 --- a/modules/cli/src/main/scala/scala/cli/ScalaCliCommands.scala +++ b/modules/cli/src/main/scala/scala/cli/ScalaCliCommands.scala @@ -42,6 +42,7 @@ class ScalaCliCommands( new HelpCmd(help), installcompletions.InstallCompletions, installhome.InstallHome, + `new`.New, repl.Repl, package0.Package, pgp.PgpPull, diff --git a/modules/cli/src/main/scala/scala/cli/commands/new/New.scala b/modules/cli/src/main/scala/scala/cli/commands/new/New.scala new file mode 100644 index 0000000000..c488493201 --- /dev/null +++ b/modules/cli/src/main/scala/scala/cli/commands/new/New.scala @@ -0,0 +1,18 @@ +package scala.cli.commands.`new` + +import scala.cli.commands.ScalaCommand +import scala.cli.commands.shared.HelpCommandGroup +import scala.build.Logger +import caseapp.core.RemainingArgs +import giter8.Giter8 + +object New extends ScalaCommand[NewOptions] { + override def group: String = HelpCommandGroup.Main.toString + + override def scalaSpecificationLevel = SpecificationLevel.IMPLEMENTATION + + override def runCommand(options: NewOptions, remainingArgs: RemainingArgs, logger: Logger): Unit = + val inputArgs = remainingArgs.remaining + Giter8.run(inputArgs.toArray) + () +} diff --git a/modules/cli/src/main/scala/scala/cli/commands/new/NewOptions.scala b/modules/cli/src/main/scala/scala/cli/commands/new/NewOptions.scala new file mode 100644 index 0000000000..c186252eee --- /dev/null +++ b/modules/cli/src/main/scala/scala/cli/commands/new/NewOptions.scala @@ -0,0 +1,25 @@ +package scala.cli.commands.`new` + +import caseapp.* +import scala.cli.commands.shared.* + +@HelpMessage(NewOptions.newMessage, "", NewOptions.detailedNewMessage) +final case class NewOptions( + @Recurse + shared: SharedOptions = SharedOptions() +) extends HasSharedOptions + +object NewOptions { + implicit lazy val parser: Parser[NewOptions] = Parser.derive + implicit lazy val help: Help[NewOptions] = Help.derive + val cmdName = "new" + private val newHeader = "New giter8 template." + val newMessage: String = HelpMessages.shortHelpMessage(cmdName, newHeader) + + val detailedNewMessage: String = + s"""$newHeader + | + | Creates a new project from a giter8 template. + | + |""".stripMargin +} diff --git a/project/deps.sc b/project/deps.sc index bffd3c3af1..7895188d29 100644 --- a/project/deps.sc +++ b/project/deps.sc @@ -113,6 +113,7 @@ object Deps { // TODO bump once 0.15.5 is out def expecty = ivy"com.eed3si9n.expecty::expecty:0.16.0" def fansi = ivy"com.lihaoyi::fansi:0.4.0" + def giter8 = ivy"org.foundweekends.giter8:giter8_2.13:0.16.2" def guava = ivy"com.google.guava:guava:32.0.0-jre" def javaClassName = ivy"io.github.alexarchambault.scala-cli:java-class-name_3:0.1.0" def jgit = ivy"org.eclipse.jgit:org.eclipse.jgit:6.5.0.202303070854-r" From 6af78b42c59a8e6d9fee1bb3511dd0166fdca576 Mon Sep 17 00:00:00 2001 From: zetashift Date: Tue, 13 Jun 2023 00:12:33 +0200 Subject: [PATCH 02/13] Use GlobalOptions instead of SharedOptions --- .../src/main/scala/scala/cli/commands/new/NewOptions.scala | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/modules/cli/src/main/scala/scala/cli/commands/new/NewOptions.scala b/modules/cli/src/main/scala/scala/cli/commands/new/NewOptions.scala index c186252eee..c91a59cf7e 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/new/NewOptions.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/new/NewOptions.scala @@ -6,8 +6,8 @@ import scala.cli.commands.shared.* @HelpMessage(NewOptions.newMessage, "", NewOptions.detailedNewMessage) final case class NewOptions( @Recurse - shared: SharedOptions = SharedOptions() -) extends HasSharedOptions + global: GlobalOptions = GlobalOptions() +) extends HasGlobalOptions object NewOptions { implicit lazy val parser: Parser[NewOptions] = Parser.derive From f5c3e45ca92d428aa8b9d44e90d0e03055cc0774 Mon Sep 17 00:00:00 2001 From: zetashift Date: Tue, 13 Jun 2023 00:13:48 +0200 Subject: [PATCH 03/13] Formatting and linting --- .../cli/src/main/scala/scala/cli/commands/new/New.scala | 7 ++++--- .../src/main/scala/scala/cli/commands/new/NewOptions.scala | 1 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/modules/cli/src/main/scala/scala/cli/commands/new/New.scala b/modules/cli/src/main/scala/scala/cli/commands/new/New.scala index c488493201..60c973d969 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/new/New.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/new/New.scala @@ -1,11 +1,12 @@ package scala.cli.commands.`new` -import scala.cli.commands.ScalaCommand -import scala.cli.commands.shared.HelpCommandGroup -import scala.build.Logger import caseapp.core.RemainingArgs import giter8.Giter8 +import scala.build.Logger +import scala.cli.commands.ScalaCommand +import scala.cli.commands.shared.HelpCommandGroup + object New extends ScalaCommand[NewOptions] { override def group: String = HelpCommandGroup.Main.toString diff --git a/modules/cli/src/main/scala/scala/cli/commands/new/NewOptions.scala b/modules/cli/src/main/scala/scala/cli/commands/new/NewOptions.scala index c91a59cf7e..517a00eb55 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/new/NewOptions.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/new/NewOptions.scala @@ -1,6 +1,7 @@ package scala.cli.commands.`new` import caseapp.* + import scala.cli.commands.shared.* @HelpMessage(NewOptions.newMessage, "", NewOptions.detailedNewMessage) From b22ad073a5f6fdf6e08a409266a442ab60daa12b Mon Sep 17 00:00:00 2001 From: zetashift Date: Tue, 13 Jun 2023 00:14:29 +0200 Subject: [PATCH 04/13] Add auto-generated docs --- website/docs/reference/cli-options.md | 8 +-- website/docs/reference/commands.md | 9 +++ .../reference/scala-command/cli-options.md | 8 +-- .../docs/reference/scala-command/commands.md | 9 +++ .../scala-command/runner-specification.md | 66 +++++++++++++++++++ 5 files changed, 92 insertions(+), 8 deletions(-) diff --git a/website/docs/reference/cli-options.md b/website/docs/reference/cli-options.md index 4371e51f88..0fcd32c86d 100644 --- a/website/docs/reference/cli-options.md +++ b/website/docs/reference/cli-options.md @@ -412,7 +412,7 @@ Pass scalafmt version before running it (3.7.4 by default). If passed, this over Available in commands: -[`add-path`](./commands.md#add-path), [`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop output`](./commands.md#bloop-output), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`default-file`](./commands.md#default-file), [`dependency-update`](./commands.md#dependency-update), [`directories`](./commands.md#directories), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`package`](./commands.md#package), [`pgp pull`](./commands.md#pgp-pull), [`pgp push`](./commands.md#pgp-push), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`github secret create` , `gh secret create`](./commands.md#github-secret-create), [`github secret list` , `gh secret list`](./commands.md#github-secret-list), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) +[`add-path`](./commands.md#add-path), [`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop output`](./commands.md#bloop-output), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`default-file`](./commands.md#default-file), [`dependency-update`](./commands.md#dependency-update), [`directories`](./commands.md#directories), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`new`](./commands.md#new), [`package`](./commands.md#package), [`pgp pull`](./commands.md#pgp-pull), [`pgp push`](./commands.md#pgp-push), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`github secret create` , `gh secret create`](./commands.md#github-secret-create), [`github secret list` , `gh secret list`](./commands.md#github-secret-list), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) @@ -426,7 +426,7 @@ Suppress warnings about using experimental features Available in commands: -[`add-path`](./commands.md#add-path), [`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop output`](./commands.md#bloop-output), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`default-file`](./commands.md#default-file), [`dependency-update`](./commands.md#dependency-update), [`directories`](./commands.md#directories), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`package`](./commands.md#package), [`pgp create`](./commands.md#pgp-create), [`pgp key-id`](./commands.md#pgp-key-id), [`pgp pull`](./commands.md#pgp-pull), [`pgp push`](./commands.md#pgp-push), [`pgp sign`](./commands.md#pgp-sign), [`pgp verify`](./commands.md#pgp-verify), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`github secret create` , `gh secret create`](./commands.md#github-secret-create), [`github secret list` , `gh secret list`](./commands.md#github-secret-list), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) +[`add-path`](./commands.md#add-path), [`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop output`](./commands.md#bloop-output), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`default-file`](./commands.md#default-file), [`dependency-update`](./commands.md#dependency-update), [`directories`](./commands.md#directories), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`new`](./commands.md#new), [`package`](./commands.md#package), [`pgp create`](./commands.md#pgp-create), [`pgp key-id`](./commands.md#pgp-key-id), [`pgp pull`](./commands.md#pgp-pull), [`pgp push`](./commands.md#pgp-push), [`pgp sign`](./commands.md#pgp-sign), [`pgp verify`](./commands.md#pgp-verify), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`github secret create` , `gh secret create`](./commands.md#github-secret-create), [`github secret list` , `gh secret list`](./commands.md#github-secret-list), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) @@ -600,7 +600,7 @@ Port for BSP debugging Available in commands: -[`add-path`](./commands.md#add-path), [`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop output`](./commands.md#bloop-output), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`default-file`](./commands.md#default-file), [`dependency-update`](./commands.md#dependency-update), [`directories`](./commands.md#directories), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`package`](./commands.md#package), [`pgp pull`](./commands.md#pgp-pull), [`pgp push`](./commands.md#pgp-push), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`github secret create` , `gh secret create`](./commands.md#github-secret-create), [`github secret list` , `gh secret list`](./commands.md#github-secret-list), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) +[`add-path`](./commands.md#add-path), [`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop output`](./commands.md#bloop-output), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`default-file`](./commands.md#default-file), [`dependency-update`](./commands.md#dependency-update), [`directories`](./commands.md#directories), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`new`](./commands.md#new), [`package`](./commands.md#package), [`pgp pull`](./commands.md#pgp-pull), [`pgp push`](./commands.md#pgp-push), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`github secret create` , `gh secret create`](./commands.md#github-secret-create), [`github secret list` , `gh secret list`](./commands.md#github-secret-list), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) @@ -1683,7 +1683,7 @@ A github token used to access GitHub. Not needed in most cases. Available in commands: -[`add-path`](./commands.md#add-path), [`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop output`](./commands.md#bloop-output), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`default-file`](./commands.md#default-file), [`dependency-update`](./commands.md#dependency-update), [`directories`](./commands.md#directories), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`package`](./commands.md#package), [`pgp pull`](./commands.md#pgp-pull), [`pgp push`](./commands.md#pgp-push), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`github secret create` , `gh secret create`](./commands.md#github-secret-create), [`github secret list` , `gh secret list`](./commands.md#github-secret-list), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) +[`add-path`](./commands.md#add-path), [`bloop`](./commands.md#bloop), [`bloop exit`](./commands.md#bloop-exit), [`bloop output`](./commands.md#bloop-output), [`bloop start`](./commands.md#bloop-start), [`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`default-file`](./commands.md#default-file), [`dependency-update`](./commands.md#dependency-update), [`directories`](./commands.md#directories), [`doc`](./commands.md#doc), [`export`](./commands.md#export), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`new`](./commands.md#new), [`package`](./commands.md#package), [`pgp pull`](./commands.md#pgp-pull), [`pgp push`](./commands.md#pgp-push), [`publish`](./commands.md#publish), [`publish local`](./commands.md#publish-local), [`publish setup`](./commands.md#publish-setup), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`github secret create` , `gh secret create`](./commands.md#github-secret-create), [`github secret list` , `gh secret list`](./commands.md#github-secret-list), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) diff --git a/website/docs/reference/commands.md b/website/docs/reference/commands.md index 29ddb81e80..1afe99071e 100644 --- a/website/docs/reference/commands.md +++ b/website/docs/reference/commands.md @@ -149,6 +149,15 @@ For detailed documentation refer to our website: https://scala-cli.virtuslab.org Accepts option groups: [global suppress warning](./cli-options.md#global-suppress-warning-options), [install completions](./cli-options.md#install-completions-options), [logging](./cli-options.md#logging-options), [verbosity](./cli-options.md#verbosity-options) +## new + +New giter8 template. + + Creates a new project from a giter8 template. + + +Accepts option groups: [global suppress warning](./cli-options.md#global-suppress-warning-options), [logging](./cli-options.md#logging-options), [verbosity](./cli-options.md#verbosity-options) + ## repl Aliases: `console` diff --git a/website/docs/reference/scala-command/cli-options.md b/website/docs/reference/scala-command/cli-options.md index 7f34a860d7..28228a51e4 100644 --- a/website/docs/reference/scala-command/cli-options.md +++ b/website/docs/reference/scala-command/cli-options.md @@ -360,7 +360,7 @@ Pass scalafmt version before running it (3.7.4 by default). If passed, this over Available in commands: -[`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`doc`](./commands.md#doc), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) +[`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`doc`](./commands.md#doc), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`new`](./commands.md#new), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) @@ -376,7 +376,7 @@ Suppress warnings about using experimental features Available in commands: -[`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`doc`](./commands.md#doc), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) +[`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`doc`](./commands.md#doc), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`new`](./commands.md#new), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) @@ -590,7 +590,7 @@ Port for BSP debugging Available in commands: -[`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`doc`](./commands.md#doc), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) +[`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`doc`](./commands.md#doc), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`new`](./commands.md#new), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) @@ -1212,7 +1212,7 @@ A github token used to access GitHub. Not needed in most cases. Available in commands: -[`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`doc`](./commands.md#doc), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) +[`bsp`](./commands.md#bsp), [`clean`](./commands.md#clean), [`compile`](./commands.md#compile), [`config`](./commands.md#config), [`doc`](./commands.md#doc), [`fmt` , `format` , `scalafmt`](./commands.md#fmt), [`help`](./commands.md#help), [`install completions` , `install-completions`](./commands.md#install-completions), [`install-home`](./commands.md#install-home), [`new`](./commands.md#new), [`repl` , `console`](./commands.md#repl), [`run`](./commands.md#run), [`setup-ide`](./commands.md#setup-ide), [`shebang`](./commands.md#shebang), [`test`](./commands.md#test), [`uninstall`](./commands.md#uninstall), [`uninstall completions` , `uninstall-completions`](./commands.md#uninstall-completions), [`update`](./commands.md#update), [`version`](./commands.md#version) diff --git a/website/docs/reference/scala-command/commands.md b/website/docs/reference/scala-command/commands.md index df7408b172..30ad76b07d 100644 --- a/website/docs/reference/scala-command/commands.md +++ b/website/docs/reference/scala-command/commands.md @@ -273,6 +273,15 @@ Install Scala CLI in a sub-directory of the home directory Accepts option groups: [global suppress warning](./cli-options.md#global-suppress-warning-options), [install home](./cli-options.md#install-home-options), [logging](./cli-options.md#logging-options), [verbosity](./cli-options.md#verbosity-options) +### new + +New giter8 template. + + Creates a new project from a giter8 template. + + +Accepts option groups: [global suppress warning](./cli-options.md#global-suppress-warning-options), [logging](./cli-options.md#logging-options), [verbosity](./cli-options.md#verbosity-options) + ### setup-ide Generates a BSP file that you can import into your IDE. diff --git a/website/docs/reference/scala-command/runner-specification.md b/website/docs/reference/scala-command/runner-specification.md index 6334e0cbf4..197e36dc7d 100644 --- a/website/docs/reference/scala-command/runner-specification.md +++ b/website/docs/reference/scala-command/runner-specification.md @@ -5057,6 +5057,72 @@ Binary directory --- +## `new` command +**IMPLEMENTATION specific for Scala Runner specification.** + +New giter8 template. + + Creates a new project from a giter8 template. + + +
+ +### Implementantation specific options + + + +**--usage** + +Print usage and exit + +**--help** + +Print help message and exit + +Aliases: `-h` ,`-help` + +**--help-full** + +Print help message, including hidden options, and exit + +Aliases: `--full-help` ,`-help-full` ,`-full-help` + +**--verbose** + +Increase verbosity (can be specified multiple times) + +Aliases: `-verbose` ,`-v` + +**--interactive** + +Interactive mode + +Aliases: `-i` + +**--actions** + +Enable actionable diagnostics + +**--quiet** + +Decrease logging verbosity + +Aliases: `-q` + +**--progress** + +Use progress bars + +**--suppress-experimental-feature-warning** + +Suppress warnings about using experimental features + +Aliases: `--suppress-experimental-warning` + +
+ +--- + ## `setup-ide` command **IMPLEMENTATION specific for Scala Runner specification.** From 0411dd3925ad2a971cd9ad60fb263aeb5964600d Mon Sep 17 00:00:00 2001 From: zetashift Date: Tue, 13 Jun 2023 22:49:01 +0200 Subject: [PATCH 05/13] Refactor to use external jar instead of giter8 as a source dependency --- build.sc | 5 +- .../scala/scala/cli/commands/new/New.scala | 50 ++++++++++++++++--- 2 files changed, 48 insertions(+), 7 deletions(-) diff --git a/build.sc b/build.sc index 1c915c9beb..22c381f093 100644 --- a/build.sc +++ b/build.sc @@ -430,6 +430,10 @@ trait Core extends ScalaCliSbtModule with ScalaCliPublishModule with HasTests | def libsodiumjniVersion = "${Deps.libsodiumjni.dep.version}" | | def scalaPyVersion = "${Deps.scalaPy.dep.version}" + | + | def giter8Organization = "${Deps.giter8.dep.module.organization.value}" + | def giter8Name = "${Deps.giter8.dep.module.name.value}" + | def giter8Version = "${Deps.giter8.dep.version}" |} |""".stripMargin if (!os.isFile(dest) || os.read(dest) != code) @@ -781,7 +785,6 @@ trait Cli extends SbtModule with ProtoBuildModule with CliLaunchers Deps.coursierLauncher, Deps.coursierProxySetup, Deps.coursierPublish.exclude((organization, "config_2.13")), - Deps.giter8, Deps.jimfs, // scalaJsEnvNodeJs pulls jimfs:1.1, whose class path seems borked (bin compat issue with the guava version it depends on) Deps.jniUtils, Deps.jsoniterCore, diff --git a/modules/cli/src/main/scala/scala/cli/commands/new/New.scala b/modules/cli/src/main/scala/scala/cli/commands/new/New.scala index 60c973d969..375394f1a0 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/new/New.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/new/New.scala @@ -1,19 +1,57 @@ package scala.cli.commands.`new` import caseapp.core.RemainingArgs -import giter8.Giter8 +import dependency.* -import scala.build.Logger +import scala.build.internal.{Constants, OsLibc, Runner} +import scala.build.options.{BuildOptions, JavaOptions} +import scala.build.{Artifacts, Logger, Positioned} import scala.cli.commands.ScalaCommand -import scala.cli.commands.shared.HelpCommandGroup +import scala.cli.commands.shared.{CoursierOptions, HelpCommandGroup} object New extends ScalaCommand[NewOptions] { override def group: String = HelpCommandGroup.Main.toString override def scalaSpecificationLevel = SpecificationLevel.IMPLEMENTATION + val giter8Dependency = + Seq(dep"${Constants.giter8Organization}::${Constants.giter8Name}:${Constants.giter8Version}") + override def runCommand(options: NewOptions, remainingArgs: RemainingArgs, logger: Logger): Unit = - val inputArgs = remainingArgs.remaining - Giter8.run(inputArgs.toArray) - () + val fetchedGiter8 = Artifacts.fetch( + Positioned.none(giter8Dependency), + Seq.empty, + None, + logger, + CoursierOptions().coursierCache(logger.coursierLogger("")), + None + ) match { + case Right(value) => value + case Left(value) => + System.err.println(value.message) + sys.exit(1) + } + + val giter8 = fetchedGiter8.fullDetailedArtifacts.collect { + case (_, _, _, Some(f)) => os.Path(f, os.pwd) + } + + val buildOptions = BuildOptions( + javaOptions = JavaOptions( + jvmIdOpt = Some(OsLibc.baseDefaultJvm(OsLibc.jvmIndexOs, "17")).map(Positioned.none) + ) + ) + + val exitCode = + Runner.runJvm( + buildOptions.javaHome().value.javaCommand, + buildOptions.javaOptions.javaOpts.toSeq.map(_.value.value), + giter8, + "giter8.Giter8", + remainingArgs.unparsed, + logger, + allowExecve = true + ).waitFor() + + sys.exit(exitCode) } From 62cc3b22f602fd5ceca2a2fbdff19a864ccd8a5f Mon Sep 17 00:00:00 2001 From: zetashift Date: Wed, 14 Jun 2023 19:39:40 +0200 Subject: [PATCH 06/13] Mark command as experimental MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Łukasz Wroński <46607934+lwronski@users.noreply.github.com> --- modules/cli/src/main/scala/scala/cli/commands/new/New.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/cli/src/main/scala/scala/cli/commands/new/New.scala b/modules/cli/src/main/scala/scala/cli/commands/new/New.scala index 375394f1a0..a067ceb53f 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/new/New.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/new/New.scala @@ -12,7 +12,7 @@ import scala.cli.commands.shared.{CoursierOptions, HelpCommandGroup} object New extends ScalaCommand[NewOptions] { override def group: String = HelpCommandGroup.Main.toString - override def scalaSpecificationLevel = SpecificationLevel.IMPLEMENTATION + override def scalaSpecificationLevel = SpecificationLevel.EXPERIMENTAL val giter8Dependency = Seq(dep"${Constants.giter8Organization}::${Constants.giter8Name}:${Constants.giter8Version}") From c85d980b8636256d932edf03a1fe4a0c3a81c09e Mon Sep 17 00:00:00 2001 From: zetashift Date: Wed, 14 Jun 2023 20:17:29 +0200 Subject: [PATCH 07/13] Add ScalaParameters and fix argument passing to giter8 --- modules/cli/src/main/scala/scala/cli/commands/new/New.scala | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/modules/cli/src/main/scala/scala/cli/commands/new/New.scala b/modules/cli/src/main/scala/scala/cli/commands/new/New.scala index a067ceb53f..269c9d0995 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/new/New.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/new/New.scala @@ -18,10 +18,11 @@ object New extends ScalaCommand[NewOptions] { Seq(dep"${Constants.giter8Organization}::${Constants.giter8Name}:${Constants.giter8Version}") override def runCommand(options: NewOptions, remainingArgs: RemainingArgs, logger: Logger): Unit = + val scalaParameters = ScalaParameters(Constants.defaultScala213Version) val fetchedGiter8 = Artifacts.fetch( Positioned.none(giter8Dependency), Seq.empty, - None, + Some(scalaParameters), logger, CoursierOptions().coursierCache(logger.coursierLogger("")), None @@ -48,7 +49,7 @@ object New extends ScalaCommand[NewOptions] { buildOptions.javaOptions.javaOpts.toSeq.map(_.value.value), giter8, "giter8.Giter8", - remainingArgs.unparsed, + remainingArgs.remaining, logger, allowExecve = true ).waitFor() From b41725810d3b99707bb4ad08e7f33554bcf790d2 Mon Sep 17 00:00:00 2001 From: zetashift Date: Wed, 14 Jun 2023 20:17:59 +0200 Subject: [PATCH 08/13] Fix giter8 ivy dependency string --- project/deps.sc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/deps.sc b/project/deps.sc index 7895188d29..5a6456143a 100644 --- a/project/deps.sc +++ b/project/deps.sc @@ -113,7 +113,7 @@ object Deps { // TODO bump once 0.15.5 is out def expecty = ivy"com.eed3si9n.expecty::expecty:0.16.0" def fansi = ivy"com.lihaoyi::fansi:0.4.0" - def giter8 = ivy"org.foundweekends.giter8:giter8_2.13:0.16.2" + def giter8 = ivy"org.foundweekends.giter8:giter8:0.16.2" def guava = ivy"com.google.guava:guava:32.0.0-jre" def javaClassName = ivy"io.github.alexarchambault.scala-cli:java-class-name_3:0.1.0" def jgit = ivy"org.eclipse.jgit:org.eclipse.jgit:6.5.0.202303070854-r" From a895b91e8e03705c5e75ce7337f8d433b99853fe Mon Sep 17 00:00:00 2001 From: zetashift Date: Sat, 17 Jun 2023 21:29:46 +0200 Subject: [PATCH 09/13] Attempt at getting integration tests working --- .../scala/cli/integration/NewTests.scala | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 modules/integration/src/test/scala/scala/cli/integration/NewTests.scala diff --git a/modules/integration/src/test/scala/scala/cli/integration/NewTests.scala b/modules/integration/src/test/scala/scala/cli/integration/NewTests.scala new file mode 100644 index 0000000000..55f956e1d4 --- /dev/null +++ b/modules/integration/src/test/scala/scala/cli/integration/NewTests.scala @@ -0,0 +1,35 @@ +package scala.cli.integration + +import com.eed3si9n.expecty.Expecty.expect + +class NewTests extends ScalaCliSuite { + override def group: ScalaCliSuite.TestGroup = ScalaCliSuite.TestGroup.First + + val simpleTemplateName = "VirtusLab/scala-cli.g8" + + val expectedTemplateContent = + """ + |object HelloWorld { + | def main(args: Array[String]): Unit = { + | println("Hello, world!") + | } + |}""".stripMargin + + val simpleTemplate: TestInputs = TestInputs( + os.rel / "HelloWorld.scala" -> expectedTemplateContent + ) + + test("simple new template") { + simpleTemplate.fromRoot { root => + os.proc(TestUtil.cli, "new", simpleTemplateName).call(cwd = root) + val content = os.read(root / "HelloWorld.scala") + expect(content == expectedTemplateContent) + } + } + + test("error without template name") { + val output = os.proc(TestUtil.cli, "new") + expect(output == output) + } + +} From 11a602b6c5eef48f7f6b5abdaf10197e19f01a22 Mon Sep 17 00:00:00 2001 From: zetashift Date: Sun, 18 Jun 2023 15:37:04 +0200 Subject: [PATCH 10/13] Improve integration tests in NewTests.scala --- .../scala/scala/cli/integration/NewTests.scala | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/modules/integration/src/test/scala/scala/cli/integration/NewTests.scala b/modules/integration/src/test/scala/scala/cli/integration/NewTests.scala index 55f956e1d4..f13ffc7760 100644 --- a/modules/integration/src/test/scala/scala/cli/integration/NewTests.scala +++ b/modules/integration/src/test/scala/scala/cli/integration/NewTests.scala @@ -2,6 +2,8 @@ package scala.cli.integration import com.eed3si9n.expecty.Expecty.expect +import scala.cli.integration.TestUtil.removeAnsiColors + class NewTests extends ScalaCliSuite { override def group: ScalaCliSuite.TestGroup = ScalaCliSuite.TestGroup.First @@ -21,15 +23,19 @@ class NewTests extends ScalaCliSuite { test("simple new template") { simpleTemplate.fromRoot { root => - os.proc(TestUtil.cli, "new", simpleTemplateName).call(cwd = root) + os.proc(TestUtil.cli, "--power", "new", simpleTemplateName).call(cwd = root) val content = os.read(root / "HelloWorld.scala") expect(content == expectedTemplateContent) } } - test("error without template name") { - val output = os.proc(TestUtil.cli, "new") - expect(output == output) + test("error missing template argument") { + TestInputs.empty.fromRoot { root => + val result = os.proc(TestUtil.cli, "--power", "new").call(cwd = root, check = false) + val lines = removeAnsiColors(result.err.text()).linesIterator.toVector + assert(result.exitCode == 1) + expect(lines.contains("Error: Missing argument