diff --git a/modules/cli/src/main/scala/scala/cli/ScalaCli.scala b/modules/cli/src/main/scala/scala/cli/ScalaCli.scala index af8be1b7f7..ff6a46850d 100644 --- a/modules/cli/src/main/scala/scala/cli/ScalaCli.scala +++ b/modules/cli/src/main/scala/scala/cli/ScalaCli.scala @@ -1,7 +1,7 @@ package scala.cli import caseapp.core.app.CommandsEntryPoint -import caseapp.core.help.RuntimeCommandsHelp +import caseapp.core.help.{Help, RuntimeCommandsHelp} import java.io.{ByteArrayOutputStream, PrintStream} import java.nio.charset.StandardCharsets @@ -40,16 +40,17 @@ object ScalaCli extends CommandsEntryPoint { Version ) - lazy val progName = (new Argv0).get("scala-cli") - override def description = "Compile, run, package Scala code." + lazy val progName = (new Argv0).get("scala-cli") + override def description = + "Scala CLI is a command-line tool to interact with the Scala language. It lets you compile, run, test, and package your Scala code." + override def summaryDesc = + "See 'scala-cli --help' to read about a specific subcommand. To see full help run 'scala-cli --help-full'." final override def defaultCommand = Some(actualDefaultCommand) // FIXME Report this in case-app default NameFormatter override lazy val help: RuntimeCommandsHelp = { val parent = super.help - parent.withDefaultHelp( - parent.defaultHelp.withNameFormatter(actualDefaultCommand.nameFormatter) - ) + parent.withDefaultHelp(Help[Unit]()) } override def enableCompleteCommand = true diff --git a/modules/cli/src/main/scala/scala/cli/commands/Bsp.scala b/modules/cli/src/main/scala/scala/cli/commands/Bsp.scala index 02865632e3..62ed493672 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/Bsp.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/Bsp.scala @@ -11,6 +11,7 @@ import scala.concurrent.Await import scala.concurrent.duration.Duration object Bsp extends ScalaCommand[BspOptions] { + override def hidden = true def run(options: BspOptions, args: RemainingArgs): Unit = { CurrentParams.verbosity = options.shared.logging.verbosity if (options.shared.logging.verbosity >= 3) diff --git a/modules/cli/src/main/scala/scala/cli/commands/Compile.scala b/modules/cli/src/main/scala/scala/cli/commands/Compile.scala index 6c126efcc9..4f058f6c00 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/Compile.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/Compile.scala @@ -11,6 +11,7 @@ object Compile extends ScalaCommand[CompileOptions] { override def group = "Main" override def sharedOptions(options: CompileOptions) = Some(options.shared) def run(options: CompileOptions, args: RemainingArgs): Unit = { + maybePrintGroupHelp(options) CurrentParams.verbosity = options.shared.logging.verbosity val inputs = options.shared.inputsOrExit(args) CurrentParams.workspaceOpt = Some(inputs.workspace) diff --git a/modules/cli/src/main/scala/scala/cli/commands/Fmt.scala b/modules/cli/src/main/scala/scala/cli/commands/Fmt.scala index 85f98b7864..3cd06924a4 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/Fmt.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/Fmt.scala @@ -8,7 +8,7 @@ import scala.cli.CurrentParams import scala.cli.internal.FetchExternalBinary object Fmt extends ScalaCommand[FmtOptions] { - override def group = "Miscellaneous" + override def group = "Main" override def sharedOptions(options: FmtOptions) = Some(options.shared) override def names = List( List("fmt"), diff --git a/modules/cli/src/main/scala/scala/cli/commands/HelpGroupOptions.scala b/modules/cli/src/main/scala/scala/cli/commands/HelpGroupOptions.scala new file mode 100644 index 0000000000..38960ea242 --- /dev/null +++ b/modules/cli/src/main/scala/scala/cli/commands/HelpGroupOptions.scala @@ -0,0 +1,35 @@ +package scala.cli.commands + +import caseapp._ +import caseapp.core.help.Help +import upickle.default.{ReadWriter, macroRW} + +import scala.cli.ScalaCli + +@HelpMessage("Print help message") +case class HelpGroupOptions( + @HelpMessage("Show options for ScalaJS") + helpJs: Boolean = false, + @HelpMessage("Show options for ScalaNative") + helpNative: Boolean = false +) { + + private def printHelpWithGroup(help: Help[_], group: String) = { + println(help.help(ScalaCli.helpFormat.withHiddenGroups( + ScalaCli.helpFormat.hiddenGroups.map(_.filterNot(_ == group)) + ))) + sys.exit(0) + } + + def maybePrintGroupHelp(help: Help[_]): Unit = { + if (helpJs) printHelpWithGroup(help, "Scala.JS") + else if (helpNative) printHelpWithGroup(help, "Scala Native") + } +} + +object HelpGroupOptions { + lazy val parser: Parser[HelpGroupOptions] = Parser.derive + implicit lazy val parserAux: Parser.Aux[HelpGroupOptions, parser.D] = parser + implicit lazy val help: Help[HelpGroupOptions] = Help.derive + implicit lazy val jsonCodec: ReadWriter[HelpGroupOptions] = macroRW +} diff --git a/modules/cli/src/main/scala/scala/cli/commands/Metabrowse.scala b/modules/cli/src/main/scala/scala/cli/commands/Metabrowse.scala index 2e93516ee0..f06b34a468 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/Metabrowse.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/Metabrowse.scala @@ -11,7 +11,8 @@ import scala.cli.CurrentParams import scala.cli.internal.FetchExternalBinary object Metabrowse extends ScalaCommand[MetabrowseOptions] { - override def group = "Miscellaneous" + override def hidden = true + override def group = "Miscellaneous" override def names = List( List("browse"), List("metabrowse") diff --git a/modules/cli/src/main/scala/scala/cli/commands/Package.scala b/modules/cli/src/main/scala/scala/cli/commands/Package.scala index 5edfa5f16f..b9a2d99bb0 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/Package.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/Package.scala @@ -34,6 +34,7 @@ object Package extends ScalaCommand[PackageOptions] { override def group = "Main" override def sharedOptions(options: PackageOptions) = Some(options.shared) def run(options: PackageOptions, args: RemainingArgs): Unit = { + maybePrintGroupHelp(options) CurrentParams.verbosity = options.shared.logging.verbosity val inputs = options.shared.inputsOrExit(args) CurrentParams.workspaceOpt = Some(inputs.workspace) diff --git a/modules/cli/src/main/scala/scala/cli/commands/PackageOptions.scala b/modules/cli/src/main/scala/scala/cli/commands/PackageOptions.scala index d7e20ef227..791cf8b235 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/PackageOptions.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/PackageOptions.scala @@ -54,7 +54,7 @@ final case class PackageOptions( pkg: Boolean = false, @Group("Package") @HelpMessage("Build Docker image") - docker: Boolean = false, + docker: Boolean = false ) { // format: on def packageTypeOpt: Option[PackageType] = diff --git a/modules/cli/src/main/scala/scala/cli/commands/Run.scala b/modules/cli/src/main/scala/scala/cli/commands/Run.scala index bdc3430f32..147200967f 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/Run.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/Run.scala @@ -17,13 +17,15 @@ object Run extends ScalaCommand[RunOptions] { override def sharedOptions(options: RunOptions) = Some(options.shared) - def run(options: RunOptions, args: RemainingArgs): Unit = + def run(options: RunOptions, args: RemainingArgs): Unit = { + maybePrintGroupHelp(options) run( options, args.remaining, args.unparsed, () => Inputs.default() ) + } def run( options: RunOptions, diff --git a/modules/cli/src/main/scala/scala/cli/commands/ScalaCommand.scala b/modules/cli/src/main/scala/scala/cli/commands/ScalaCommand.scala index e08966c3e2..4eca8a0434 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/ScalaCommand.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/ScalaCommand.scala @@ -84,6 +84,11 @@ abstract class ScalaCommand[T](implicit parser: Parser[T], help: Help[T]) parent.argument(prefix, state) } } + + def maybePrintGroupHelp(options: T): Unit = + for (shared <- sharedOptions(options)) + shared.helpGroups.maybePrintGroupHelp(help) + override def helpFormat = HelpFormat.default() .withSortedGroups(Some(Seq( @@ -101,6 +106,10 @@ abstract class ScalaCommand[T](implicit parser: Parser[T], help: Help[T]) "Miscellaneous", "" ))) + .withHiddenGroups(Some(Seq( + "Scala.JS", + "Scala Native" + ))) .withTerminalWidthOpt { if (Properties.isWin) if (coursier.paths.Util.useJni()) diff --git a/modules/cli/src/main/scala/scala/cli/commands/ScalaJsOptions.scala b/modules/cli/src/main/scala/scala/cli/commands/ScalaJsOptions.scala index 6163837ef1..f731718786 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/ScalaJsOptions.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/ScalaJsOptions.scala @@ -9,7 +9,7 @@ import scala.build.options final case class ScalaJsOptions( @Group("Scala") - @HelpMessage("Enable Scala.JS") + @HelpMessage("Enable Scala.JS. To show more options for Scala.Js pass `--help-js`") js: Boolean = false, @Group("Scala.JS") diff --git a/modules/cli/src/main/scala/scala/cli/commands/ScalaNativeOptions.scala b/modules/cli/src/main/scala/scala/cli/commands/ScalaNativeOptions.scala index ebedd6b79b..3faae54268 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/ScalaNativeOptions.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/ScalaNativeOptions.scala @@ -9,7 +9,7 @@ import scala.build.options final case class ScalaNativeOptions( @Group("Scala") - @HelpMessage("Enable Scala Native") + @HelpMessage("Enable Scala Native. To show more options for Scala Native pass `--help-native`") native: Boolean = false, @Group("Scala Native") diff --git a/modules/cli/src/main/scala/scala/cli/commands/SharedOptions.scala b/modules/cli/src/main/scala/scala/cli/commands/SharedOptions.scala index fabf128788..cfdcd2342b 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/SharedOptions.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/SharedOptions.scala @@ -100,6 +100,8 @@ final case class SharedOptions( defaultForbiddenDirectories: Boolean = true, @Hidden forbid: List[String] = Nil, + @Recurse + helpGroups: HelpGroupOptions = HelpGroupOptions() ) { // format: on diff --git a/modules/cli/src/main/scala/scala/cli/commands/Test.scala b/modules/cli/src/main/scala/scala/cli/commands/Test.scala index e3a448c6b6..e42e2d555a 100644 --- a/modules/cli/src/main/scala/scala/cli/commands/Test.scala +++ b/modules/cli/src/main/scala/scala/cli/commands/Test.scala @@ -18,6 +18,7 @@ object Test extends ScalaCommand[TestOptions] { private def reset = Console.RESET def run(options: TestOptions, args: RemainingArgs): Unit = { + maybePrintGroupHelp(options) CurrentParams.verbosity = options.shared.logging.verbosity val inputs = options.shared.inputsOrExit(args) CurrentParams.workspaceOpt = Some(inputs.workspace) diff --git a/modules/cli/src/test/scala/cli/tests/HelpCheck.scala b/modules/cli/src/test/scala/cli/tests/HelpCheck.scala new file mode 100644 index 0000000000..e481fb99ac --- /dev/null +++ b/modules/cli/src/test/scala/cli/tests/HelpCheck.scala @@ -0,0 +1,13 @@ +package cli.tests + +import scala.cli.ScalaCli + +class HelpCheck extends munit.FunSuite { + + test("help message should be shorter then 80 lines") { + val helpMessage = ScalaCli.help.help(ScalaCli.helpFormat) + + val lines = helpMessage.split("\r\n|\r|\n").length + assert(lines <= 80) + } +} diff --git a/website/docs/reference/cli-options.md b/website/docs/reference/cli-options.md index ffd3b6e0a8..da7dcc4232 100644 --- a/website/docs/reference/cli-options.md +++ b/website/docs/reference/cli-options.md @@ -362,6 +362,32 @@ Aliases: `--full-help` Print help message, including hidden options, and exit +## Help group options + +Available in commands: +- [`bsp`](./commands.md#bsp) +- [`compile`](./commands.md#compile) +- [`export`](./commands.md#export) +- [`fmt` / `format` / `scalafmt`](./commands.md#fmt) +- [`browse` / `metabrowse`](./commands.md#browse) +- [`package`](./commands.md#package) +- [`console` / `repl`](./commands.md#console) +- [`run`](./commands.md#run) +- [`setup-ide`](./commands.md#setup-ide) +- [`shebang`](./commands.md#shebang) +- [`test`](./commands.md#test) + + + + +#### `--help-js` + +Show options for ScalaJS + +#### `--help-native` + +Show options for ScalaNative + ## Install completions options Available in commands: @@ -779,7 +805,7 @@ Available in commands: #### `--js` -Enable Scala.JS +Enable Scala.JS. To show more options for Scala.Js pass `--help-js` #### `--js-version` @@ -823,7 +849,7 @@ Available in commands: #### `--native` -Enable Scala Native +Enable Scala Native. To show more options for Scala Native pass `--help-native` #### `--native-version` diff --git a/website/docs/reference/commands.md b/website/docs/reference/commands.md index 81b4263e91..96fe0290e1 100644 --- a/website/docs/reference/commands.md +++ b/website/docs/reference/commands.md @@ -10,24 +10,6 @@ Print details about this application Accepts options: - [verbosity](./cli-options.md#verbosity-options) -## `bsp` - -Start BSP server - -Accepts options: -- [bsp](./cli-options.md#bsp-options) -- [compilation server](./cli-options.md#compilation-server-options) -- [coursier](./cli-options.md#coursier-options) -- [dependency](./cli-options.md#dependency-options) -- [directories](./cli-options.md#directories-options) -- [jvm](./cli-options.md#jvm-options) -- [logging](./cli-options.md#logging-options) -- [Scala.JS](./cli-options.md#scalajs-options) -- [Scala Native](./cli-options.md#scala-native-options) -- [scalac](./cli-options.md#scalac-options) -- [shared](./cli-options.md#shared-options) -- [verbosity](./cli-options.md#verbosity-options) - ## `clean` Clean the workspace @@ -49,6 +31,7 @@ Accepts options: - [cross](./cli-options.md#cross-options) - [dependency](./cli-options.md#dependency-options) - [directories](./cli-options.md#directories-options) +- [help group](./cli-options.md#help-group-options) - [jvm](./cli-options.md#jvm-options) - [logging](./cli-options.md#logging-options) - [Scala.JS](./cli-options.md#scalajs-options) @@ -68,6 +51,7 @@ Accepts options: - [dependency](./cli-options.md#dependency-options) - [directories](./cli-options.md#directories-options) - [export](./cli-options.md#export-options) +- [help group](./cli-options.md#help-group-options) - [jvm](./cli-options.md#jvm-options) - [logging](./cli-options.md#logging-options) - [main class](./cli-options.md#main-class-options) @@ -91,6 +75,7 @@ Accepts options: - [dependency](./cli-options.md#dependency-options) - [directories](./cli-options.md#directories-options) - [fmt](./cli-options.md#fmt-options) +- [help group](./cli-options.md#help-group-options) - [jvm](./cli-options.md#jvm-options) - [logging](./cli-options.md#logging-options) - [Scala.JS](./cli-options.md#scalajs-options) @@ -116,27 +101,6 @@ Accepts options: - [logging](./cli-options.md#logging-options) - [verbosity](./cli-options.md#verbosity-options) -## `browse` - -Aliases: -- `metabrowse` - -Browse Scala code and its dependencies in the browser - -Accepts options: -- [compilation server](./cli-options.md#compilation-server-options) -- [coursier](./cli-options.md#coursier-options) -- [dependency](./cli-options.md#dependency-options) -- [directories](./cli-options.md#directories-options) -- [jvm](./cli-options.md#jvm-options) -- [logging](./cli-options.md#logging-options) -- [metabrowse](./cli-options.md#metabrowse-options) -- [Scala.JS](./cli-options.md#scalajs-options) -- [Scala Native](./cli-options.md#scala-native-options) -- [scalac](./cli-options.md#scalac-options) -- [shared](./cli-options.md#shared-options) -- [verbosity](./cli-options.md#verbosity-options) - ## `console` Aliases: @@ -150,6 +114,7 @@ Accepts options: - [coursier](./cli-options.md#coursier-options) - [dependency](./cli-options.md#dependency-options) - [directories](./cli-options.md#directories-options) +- [help group](./cli-options.md#help-group-options) - [java](./cli-options.md#java-options) - [jvm](./cli-options.md#jvm-options) - [logging](./cli-options.md#logging-options) @@ -171,6 +136,7 @@ Accepts options: - [coursier](./cli-options.md#coursier-options) - [dependency](./cli-options.md#dependency-options) - [directories](./cli-options.md#directories-options) +- [help group](./cli-options.md#help-group-options) - [jvm](./cli-options.md#jvm-options) - [logging](./cli-options.md#logging-options) - [main class](./cli-options.md#main-class-options) @@ -200,6 +166,7 @@ Accepts options: - [coursier](./cli-options.md#coursier-options) - [dependency](./cli-options.md#dependency-options) - [directories](./cli-options.md#directories-options) +- [help group](./cli-options.md#help-group-options) - [java](./cli-options.md#java-options) - [jvm](./cli-options.md#jvm-options) - [logging](./cli-options.md#logging-options) @@ -221,6 +188,7 @@ Accepts options: - [coursier](./cli-options.md#coursier-options) - [dependency](./cli-options.md#dependency-options) - [directories](./cli-options.md#directories-options) +- [help group](./cli-options.md#help-group-options) - [jvm](./cli-options.md#jvm-options) - [logging](./cli-options.md#logging-options) - [Scala.JS](./cli-options.md#scalajs-options) @@ -263,6 +231,7 @@ Accepts options: - [coursier](./cli-options.md#coursier-options) - [dependency](./cli-options.md#dependency-options) - [directories](./cli-options.md#directories-options) +- [help group](./cli-options.md#help-group-options) - [java](./cli-options.md#java-options) - [jvm](./cli-options.md#jvm-options) - [logging](./cli-options.md#logging-options) @@ -284,6 +253,7 @@ Accepts options: - [coursier](./cli-options.md#coursier-options) - [dependency](./cli-options.md#dependency-options) - [directories](./cli-options.md#directories-options) +- [help group](./cli-options.md#help-group-options) - [java](./cli-options.md#java-options) - [jvm](./cli-options.md#jvm-options) - [logging](./cli-options.md#logging-options) @@ -337,6 +307,25 @@ Accepts options: - [logging](./cli-options.md#logging-options) - [verbosity](./cli-options.md#verbosity-options) +### `bsp` + +Start BSP server + +Accepts options: +- [bsp](./cli-options.md#bsp-options) +- [compilation server](./cli-options.md#compilation-server-options) +- [coursier](./cli-options.md#coursier-options) +- [dependency](./cli-options.md#dependency-options) +- [directories](./cli-options.md#directories-options) +- [help group](./cli-options.md#help-group-options) +- [jvm](./cli-options.md#jvm-options) +- [logging](./cli-options.md#logging-options) +- [Scala.JS](./cli-options.md#scalajs-options) +- [Scala Native](./cli-options.md#scala-native-options) +- [scalac](./cli-options.md#scalac-options) +- [shared](./cli-options.md#shared-options) +- [verbosity](./cli-options.md#verbosity-options) + ### `directories` Prints directories used by `scala-cli` @@ -353,3 +342,25 @@ Accepts options: - [install home](./cli-options.md#install-home-options) - [verbosity](./cli-options.md#verbosity-options) +### `browse` + +Aliases: +- `metabrowse` + +Browse Scala code and its dependencies in the browser + +Accepts options: +- [compilation server](./cli-options.md#compilation-server-options) +- [coursier](./cli-options.md#coursier-options) +- [dependency](./cli-options.md#dependency-options) +- [directories](./cli-options.md#directories-options) +- [help group](./cli-options.md#help-group-options) +- [jvm](./cli-options.md#jvm-options) +- [logging](./cli-options.md#logging-options) +- [metabrowse](./cli-options.md#metabrowse-options) +- [Scala.JS](./cli-options.md#scalajs-options) +- [Scala Native](./cli-options.md#scala-native-options) +- [scalac](./cli-options.md#scalac-options) +- [shared](./cli-options.md#shared-options) +- [verbosity](./cli-options.md#verbosity-options) +