Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Include launcher options in the help for the default and help sub-commands #1725

Merged
merged 1 commit into from
Jan 2, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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