Skip to content

Commit

Permalink
Include launcher options in the help for the default and help sub-c…
Browse files Browse the repository at this point in the history
…ommands (#1725)
  • Loading branch information
Gedochao committed Jan 2, 2023
1 parent 8fdaccb commit adf9e3a
Show file tree
Hide file tree
Showing 9 changed files with 98 additions and 32 deletions.
5 changes: 4 additions & 1 deletion modules/cli/src/main/scala/scala/cli/ScalaCliCommands.scala
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,10 @@ class ScalaCliCommands(

override def summaryDesc =
s"""|See '$baseRunnerName <command> --help' to read about a specific subcommand. To see full help run '$baseRunnerName <command> --help-full'.
|To run another $fullRunnerName version, specify it with '--cli-version' before any other argument, like '$baseRunnerName --cli-version <version> args'.""".stripMargin
|
|To use launcher options, specify them before any other argument.
|For example, to run another $fullRunnerName version, specify it with the '--cli-version' launcher option:
| ${Console.BOLD}$baseRunnerName --cli-version <version> args${Console.RESET}""".stripMargin
final override def defaultCommand = Some(actualDefaultCommand)

// FIXME Report this in case-app default NameFormatter
Expand Down
5 changes: 3 additions & 2 deletions modules/cli/src/main/scala/scala/cli/commands/HelpCmd.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@ import caseapp.core.help.RuntimeCommandsHelp
import scala.build.Logger
import scala.cli.commands.shared.{HelpOptions, ScalaCliHelp}

class HelpCmd(actualHelp: => RuntimeCommandsHelp) extends ScalaCommand[HelpOptions] {
class HelpCmd(actualHelp: => RuntimeCommandsHelp)
extends ScalaCommandWithCustomHelp[HelpOptions](actualHelp) {
override def names = List(List("help"))
override def scalaSpecificationLevel = SpecificationLevel.IMPLEMENTATION

override def runCommand(options: HelpOptions, args: RemainingArgs, logger: Logger): Unit =
println(actualHelp.help(ScalaCliHelp.helpFormat))
customHelpAsked(showHidden = false)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package scala.cli.commands

import caseapp.core.Error
import caseapp.core.help.{Help, HelpCompanion, RuntimeCommandsHelp}
import caseapp.core.parser.Parser

import scala.cli.commands.default.DefaultOptions
import scala.cli.commands.shared.{HasLoggingOptions, ScalaCliHelp}
import scala.cli.commands.util.HelpUtils.*
import scala.cli.launcher.LauncherOptions

abstract class ScalaCommandWithCustomHelp[T <: HasLoggingOptions](
actualHelp: => RuntimeCommandsHelp
)(
implicit
myParser: Parser[T],
help: Help[T]
) extends ScalaCommand[T] {
private def launcherHelp: Help[LauncherOptions] = HelpCompanion.deriveHelp[LauncherOptions]

protected def customHelp(showHidden: Boolean): String = {
val helpString = actualHelp.help(helpFormat, showHidden)
val launcherHelpString = launcherHelp.optionsHelp(helpFormat, showHidden)
s"""$helpString
|
|$launcherHelpString""".stripMargin
}

protected def customHelpAsked(showHidden: Boolean): Nothing = {
println(customHelp(showHidden))
sys.exit(0)
}
override def helpAsked(progName: String, maybeOptions: Either[Error, T]): Nothing =
customHelpAsked(showHidden = false)
override def fullHelpAsked(progName: String): Nothing = customHelpAsked(showHidden = true)
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
package scala.cli.commands.default

import caseapp.core.help.RuntimeCommandsHelp
import caseapp.core.help.{Help, HelpCompanion, RuntimeCommandsHelp}
import caseapp.core.{Error, RemainingArgs}

import scala.build.Logger
import scala.build.internal.Constants
import scala.build.options.BuildOptions
import scala.cli.CurrentParams
import scala.cli.commands.ScalaCommand
import scala.cli.commands.repl.{Repl, ReplOptions}
import scala.cli.commands.run.{Run, RunOptions}
import scala.cli.commands.shared.{ScalaCliHelp, SharedOptions}
import scala.cli.commands.shared.ScalaCliHelp.helpFormat
import scala.cli.commands.shared.SharedOptions
import scala.cli.commands.version.Version
import scala.cli.commands.{ScalaCommand, ScalaCommandWithCustomHelp}
import scala.cli.launcher.LauncherOptions

class Default(
actualHelp: => RuntimeCommandsHelp,
isSipScala: Boolean
) extends ScalaCommand[DefaultOptions] {
) extends ScalaCommandWithCustomHelp[DefaultOptions](actualHelp) {

private lazy val defaultCommandHelp: String =
s"""
Expand All @@ -29,10 +31,8 @@ class Default(
| - if a main class was passed with the '--main-class' option alongside an extra '--classpath'
| - otherwise, if no inputs were passed, it defaults to the 'repl' subcommand""".stripMargin

private def defaultHelp: String = actualHelp.help(ScalaCliHelp.helpFormat) + defaultCommandHelp

private def defaultFullHelp: String =
actualHelp.help(ScalaCliHelp.helpFormat, showHidden = true) + defaultCommandHelp
override def customHelp(showHidden: Boolean): String =
super.customHelp(showHidden) + defaultCommandHelp

override def scalaSpecificationLevel = SpecificationLevel.MUST

Expand All @@ -42,16 +42,6 @@ class Default(

private[cli] var rawArgs = Array.empty[String]

override def helpAsked(progName: String, maybeOptions: Either[Error, DefaultOptions]): Nothing = {
println(defaultHelp)
sys.exit(0)
}

override def fullHelpAsked(progName: String): Nothing = {
println(defaultFullHelp)
sys.exit(0)
}

override def runCommand(options: DefaultOptions, args: RemainingArgs, logger: Logger): Unit =
if options.version then println(Version.versionInfo)
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@ object ScalaCliHelp {
"Package",
"Metabrowse server",
"Logging",
"Runner"
"Runner",
"Launcher"
)
),
sortedCommandGroups = Some(
Expand Down
19 changes: 19 additions & 0 deletions modules/cli/src/main/scala/scala/cli/commands/util/HelpUtils.scala
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package scala.cli.commands.util

import caseapp.core.help.{Help, HelpFormat}

object HelpUtils {
extension (help: Help[_]) {
private def abstractHelp(
format: HelpFormat,
showHidden: Boolean
)(f: (StringBuilder, HelpFormat, Boolean) => Unit): String = {
val b = new StringBuilder
f(b, format, showHidden)
b.result()
}

def optionsHelp(format: HelpFormat, showHidden: Boolean = false): String =
abstractHelp(format, showHidden)(help.printOptions)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ import caseapp.*
final case class LauncherOptions(
@Group("Launcher")
@HelpMessage("Set the Scala CLI version")
@ValueDescription("nightly|version")
cliVersion: Option[String] = None,
@Group("Launcher")
@HelpMessage("The version of Scala on which Scala CLI was published")
@ValueDescription("2.12|2.13|3")
@Hidden
cliScalaVersion: Option[String] = None,
@Group("Launcher")
@HelpMessage("When called as 'scala', allow to use power commands too")
@Hidden
power: Boolean = false
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,21 +2,36 @@ package scala.cli.integration

import com.eed3si9n.expecty.Expecty.expect

import scala.cli.integration.HelpTests.HelpVariants

class HelpTests extends ScalaCliSuite {
for { helpOption <- Seq("help", "-help", "--help") } {
val help = os.proc(TestUtil.cli, helpOption).call(check = false)
val helpOutput = help.out.trim()
test(s"$helpOption works correctly") {
assert(help.exitCode == 0, clues(helpOption, help.out.text(), help.err.text(), help.exitCode))
for { helpOptions <- HelpVariants } {
val help = os.proc(TestUtil.cli, helpOptions).call(check = false)
val helpOutput = help.out.trim()
val helpOptionsString = helpOptions.mkString(" ")
test(s"$helpOptionsString works correctly") {
assert(
help.exitCode == 0,
clues(helpOptions, help.out.text(), help.err.text(), help.exitCode)
)
expect(helpOutput.contains("Usage:"))
}

test(s"$helpOption output command groups are ordered correctly") {
test(s"$helpOptionsString output command groups are ordered correctly") {
val mainCommandsIndex = helpOutput.indexOf("Main commands:")
val miscellaneousIndex = helpOutput.indexOf("Miscellaneous commands:")
expect(mainCommandsIndex < miscellaneousIndex)
expect(miscellaneousIndex < helpOutput.indexOf("Other commands:"))
}

test(s"$helpOptionsString output includes launcher options") {
expect(helpOutput.contains("--power"))
}
}

}

object HelpTests {
val HelpVariants =
Seq(Seq("help"), Seq("help", "-help"), Seq("help", "--help"), Seq("-help"), Seq("--help"))
}
Original file line number Diff line number Diff line change
Expand Up @@ -109,9 +109,9 @@ class SipScalaTests extends ScalaCliSuite {

def testHelpOutput(binaryName: String): Unit = TestInputs.empty.fromRoot { root =>
val binary = binaryName.prepareBinary(root)
for { helpOption <- Seq("help", "-help", "--help") } {
val res = os.proc(binary, helpOption).call(cwd = root)
val restrictedFeaturesMentioned = res.out.trim().contains("package")
for { helpOptions <- HelpTests.HelpVariants } {
val output = os.proc(binary, helpOptions).call(cwd = root).out.trim()
val restrictedFeaturesMentioned = output.contains("package")
if (binaryName.isSip) expect(!restrictedFeaturesMentioned)
else expect(restrictedFeaturesMentioned)
}
Expand Down

0 comments on commit adf9e3a

Please sign in to comment.