Skip to content

Commit ea6155c

Browse files
committed
Add --envs-help to print available environment variables
1 parent 9c761b7 commit ea6155c

File tree

7 files changed

+164
-30
lines changed

7 files changed

+164
-30
lines changed

modules/cli/src/main/scala/scala/cli/commands/ScalaCommand.scala

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import scala.build.errors.BuildException
2020
import scala.build.input.{ScalaCliInvokeData, SubCommand}
2121
import scala.build.internal.util.WarningMessages
2222
import scala.build.internal.{Constants, Runner}
23-
import scala.build.internals.FeatureType
23+
import scala.build.internals.{EnvsUtil, FeatureType}
2424
import scala.build.options.{BuildOptions, ScalacOpt, Scope}
2525
import scala.build.{Artifacts, Directories, Logger, Positioned, ReplArtifacts}
2626
import scala.cli.commands.default.LegacyScalaOptions
@@ -284,6 +284,11 @@ abstract class ScalaCommand[T <: HasGlobalOptions](implicit myParser: Parser[T],
284284
sys.exit(exitCode.orExit(logger))
285285
}
286286

287+
private def maybePrintEnvsHelp(options: T): Unit =
288+
if sharedOptions(options).exists(_.helpGroups.helpEnvs) then
289+
println(EnvsUtil.helpMessage(isPower = allowRestrictedFeatures))
290+
sys.exit(0)
291+
287292
override def helpFormat: HelpFormat = ScalaCliHelp.helpFormat
288293

289294
override val messages: Help[T] =
@@ -378,6 +383,7 @@ abstract class ScalaCommand[T <: HasGlobalOptions](implicit myParser: Parser[T],
378383
maybePrintSimpleScalacOutput(options, bo)
379384
maybePrintToolsHelp(options, bo)
380385
}
386+
maybePrintEnvsHelp(options)
381387
logger.flushExperimentalWarnings
382388
runCommand(options, remainingArgs, options.global.logging.logger)
383389
}

modules/cli/src/main/scala/scala/cli/commands/shared/HelpGroupOptions.scala

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ import scala.cli.commands.tags
1010

1111
@HelpMessage("Print help message")
1212
case class HelpGroupOptions(
13+
@Group(HelpGroup.Help.toString)
14+
@HelpMessage("Show environment variable help")
15+
@Tag(tags.implementation)
16+
@Tag(tags.inShortHelp)
17+
@Name("helpEnv")
18+
@Name("envHelp")
19+
@Name("envsHelp")
20+
helpEnvs: Boolean = false,
1321
@Group(HelpGroup.Help.toString)
1422
@HelpMessage("Show options for ScalaJS")
1523
@Tag(tags.implementation)

modules/core/src/main/scala/scala/build/internals/EnvsUtil.scala

Lines changed: 72 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,21 @@
11
package scala.build.internals
22

3+
import scala.build.internals.ConsoleUtils.ScalaCliConsole
4+
35
object EnvsUtil {
6+
def helpMessage(isPower: Boolean): String =
7+
s"""The following is the list of environment variables used and recognized by Scala CLI.
8+
|It should by no means be treated as an exhaustive list
9+
|Some tools and libraries Scala CLI integrates with may have their own, which may or may not be listed here.
10+
|${if isPower then "" else "For the expanded list, pass --power." + System.lineSeparator()}
11+
|${
12+
val maxFullNameLength =
13+
EnvVar.all.filter(!_.requiresPower || isPower).map(_.name.length).max
14+
EnvVar.allGroups
15+
.map(_.subsectionMessage(maxFullNameLength, isPower))
16+
.filter(_.linesIterator.size > 1)
17+
.mkString(s"${System.lineSeparator() * 2}")
18+
}""".stripMargin
419

520
/** @param name
621
* The name of the environment variable
@@ -9,30 +24,54 @@ object EnvsUtil {
924
* @param passToIde
1025
* Whether to pass this variable to the IDE/BSP client (true by default, should only be
1126
* disabled for env vars which aren't safe to save on disk)
27+
* @param requiresPower
28+
* Whether this variable is related to a feature that requires power mode; also used for
29+
* internal toggles and such
1230
*/
13-
case class EnvVar(name: String, description: String, passToIde: Boolean = true) {
31+
case class EnvVar(
32+
name: String,
33+
description: String,
34+
passToIde: Boolean = true,
35+
requiresPower: Boolean = false
36+
) {
1437
def valueOpt: Option[String] = Option(System.getenv(name))
1538
override def toString: String = s"$name=${valueOpt.getOrElse("")}"
39+
def helpMessage(spaces: String): String = {
40+
val powerString =
41+
if requiresPower then s"${ScalaCliConsole.GRAY}(power)${Console.RESET} " else ""
42+
s"${Console.YELLOW}$name${Console.RESET}$spaces$powerString$description"
43+
}
1644
}
1745
object EnvVar {
18-
def all: Set[EnvVar] = Set(
19-
EnvVar.Java.all,
20-
EnvVar.Misc.all,
21-
EnvVar.Coursier.all,
22-
EnvVar.ScalaCli.all,
23-
EnvVar.Spark.all,
24-
EnvVar.Internal.all
25-
).flatten
26-
def allBsp: Set[EnvVar] = all.filter(_.passToIde)
27-
object Java {
28-
def all = Set(javaHome, javaOpts, jdkJavaOpts)
29-
val javaHome = EnvVar("JAVA_HOME", "Java installation directory")
30-
val javaOpts = EnvVar("JAVA_OPTS", "Java options")
31-
val jdkJavaOpts = EnvVar("JDK_JAVA_OPTIONS", "JDK Java options")
46+
trait EnvVarGroup {
47+
def all: Seq[EnvVar]
48+
def groupName: String
49+
def subsectionMessage(maxFullNameLength: Int, isPower: Boolean): String = {
50+
val envsToInclude = all.filter(!_.requiresPower || isPower)
51+
s"""$groupName
52+
|${
53+
envsToInclude
54+
.map(ev =>
55+
s" ${ev.helpMessage(spaces = " " * (maxFullNameLength - ev.name.length + 2))}"
56+
)
57+
.mkString(System.lineSeparator())
58+
}""".stripMargin
59+
}
60+
}
61+
def allGroups: Seq[EnvVarGroup] = Seq(ScalaCli, Java, Coursier, Spark, Misc, Internal)
62+
def all: Seq[EnvVar] = allGroups.flatMap(_.all)
63+
def allBsp: Seq[EnvVar] = all.filter(_.passToIde)
64+
object Java extends EnvVarGroup {
65+
override def groupName: String = "Java"
66+
override def all = Seq(javaHome, javaOpts, jdkJavaOpts)
67+
val javaHome = EnvVar("JAVA_HOME", "Java installation directory")
68+
val javaOpts = EnvVar("JAVA_OPTS", "Java options")
69+
val jdkJavaOpts = EnvVar("JDK_JAVA_OPTIONS", "JDK Java options")
3270
}
3371

34-
object Misc {
35-
def all = Set(
72+
object Misc extends EnvVarGroup {
73+
override def groupName: String = "Miscellaneous"
74+
override def all = Seq(
3675
path,
3776
dyldLibraryPath,
3877
ldLibraryPath,
@@ -50,14 +89,16 @@ object EnvsUtil {
5089
val zDotDir = EnvVar("ZDOTDIR", "Zsh configuration directory")
5190
}
5291

53-
object Coursier {
54-
def all = Set(coursierCache, coursierMode)
55-
val coursierCache = EnvVar("COURSIER_CACHE", "Coursier cache location")
56-
val coursierMode = EnvVar("COURSIER_MODE", "Coursier mode (can be set to 'offline')")
92+
object Coursier extends EnvVarGroup {
93+
override def groupName: String = "Coursier"
94+
override def all = Seq(coursierCache, coursierMode)
95+
val coursierCache = EnvVar("COURSIER_CACHE", "Coursier cache location")
96+
val coursierMode = EnvVar("COURSIER_MODE", "Coursier mode (can be set to 'offline')")
5797
}
5898

59-
object ScalaCli {
60-
def all = Set(
99+
object ScalaCli extends EnvVarGroup {
100+
override def groupName: String = "Scala CLI"
101+
def all = Seq(
61102
config,
62103
home,
63104
interactive,
@@ -78,14 +119,16 @@ object EnvsUtil {
78119
EnvVar("SCALA_CLI_VENDORED_ZIS", "Toggle io.github.scala_cli.zip.ZipInputStream")
79120
}
80121

81-
object Spark {
82-
def all = Set(sparkHome)
83-
val sparkHome = EnvVar("SPARK_HOME", "Spark installation directory")
122+
object Spark extends EnvVarGroup {
123+
override def groupName: String = "Spark"
124+
override def all = Seq(sparkHome)
125+
val sparkHome = EnvVar("SPARK_HOME", "Spark installation directory", requiresPower = true)
84126
}
85127

86-
object Internal {
87-
def all = Set(ci)
88-
val ci = EnvVar("CI", "Marker for running on the CI")
128+
object Internal extends EnvVarGroup {
129+
override def groupName: String = "Internal"
130+
def all = Seq(ci)
131+
val ci = EnvVar("CI", "Marker for running on the CI", requiresPower = true)
89132
}
90133
}
91134

modules/integration/src/test/scala/scala/cli/integration/HelpTests.scala

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,15 @@ class HelpTests extends ScalaCliSuite {
7272
"-cp, --jar, --jars, --class, --classes, -classpath, --extra-jar, --classpath, --extra-jars, --class-path, --extra-class, --extra-classes, --extra-class-path paths"
7373
))
7474
}
75+
for (withPower <- Seq(true, false))
76+
test("envs help" + (if (withPower) " with power" else "")) {
77+
val powerOptions = if (withPower) Seq("--power") else Nil
78+
val help = os.proc(TestUtil.cli, "--envs-help", powerOptions).call()
79+
val helpOutput = help.out.trim()
80+
if (!withPower) expect(!helpOutput.contains("(power)"))
81+
expect(helpOutput.nonEmpty)
82+
expect(helpOutput.contains("environment variables"))
83+
}
7584
}
7685

7786
object HelpTests {

website/docs/reference/cli-options.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,6 +495,12 @@ Available in commands:
495495

496496
<!-- Automatically generated, DO NOT EDIT MANUALLY -->
497497

498+
### `--help-envs`
499+
500+
Aliases: `--env-help`, `--envs-help`, `--help-env`
501+
502+
Show environment variable help
503+
498504
### `--help-js`
499505

500506
Show options for ScalaJS

website/docs/reference/scala-command/cli-options.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -426,6 +426,14 @@ Available in commands:
426426

427427
<!-- Automatically generated, DO NOT EDIT MANUALLY -->
428428

429+
### `--help-envs`
430+
431+
Aliases: `--env-help`, `--envs-help`, `--help-env`
432+
433+
`IMPLEMENTATION specific` per Scala Runner specification
434+
435+
Show environment variable help
436+
429437
### `--help-js`
430438

431439
`IMPLEMENTATION specific` per Scala Runner specification

website/docs/reference/scala-command/runner-specification.md

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -586,6 +586,12 @@ Should include Scala CLI runner on the runtime ClassPath. Runner is added by def
586586

587587

588588

589+
**--help-envs**
590+
591+
Show environment variable help
592+
593+
Aliases: `--help-env` ,`--env-help` ,`--envs-help`
594+
589595
**--help-js**
590596

591597
Show options for ScalaJS
@@ -1339,6 +1345,12 @@ Should include Scala CLI runner on the runtime ClassPath. Runner is added by def
13391345

13401346

13411347

1348+
**--help-envs**
1349+
1350+
Show environment variable help
1351+
1352+
Aliases: `--help-env` ,`--env-help` ,`--envs-help`
1353+
13421354
**--help-js**
13431355

13441356
Show options for ScalaJS
@@ -1924,6 +1936,12 @@ Should include Scala CLI runner on the runtime ClassPath. Runner is added by def
19241936

19251937

19261938

1939+
**--help-envs**
1940+
1941+
Show environment variable help
1942+
1943+
Aliases: `--help-env` ,`--env-help` ,`--envs-help`
1944+
19271945
**--help-js**
19281946

19291947
Show options for ScalaJS
@@ -2533,6 +2551,12 @@ Should include Scala CLI runner on the runtime ClassPath. Runner is added by def
25332551

25342552

25352553

2554+
**--help-envs**
2555+
2556+
Show environment variable help
2557+
2558+
Aliases: `--help-env` ,`--env-help` ,`--envs-help`
2559+
25362560
**--help-js**
25372561

25382562
Show options for ScalaJS
@@ -3151,6 +3175,12 @@ Should include Scala CLI runner on the runtime ClassPath. Runner is added by def
31513175

31523176

31533177

3178+
**--help-envs**
3179+
3180+
Show environment variable help
3181+
3182+
Aliases: `--help-env` ,`--env-help` ,`--envs-help`
3183+
31543184
**--help-js**
31553185

31563186
Show options for ScalaJS
@@ -3727,6 +3757,12 @@ Should include Scala CLI runner on the runtime ClassPath. Runner is added by def
37273757

37283758

37293759

3760+
**--help-envs**
3761+
3762+
Show environment variable help
3763+
3764+
Aliases: `--help-env` ,`--env-help` ,`--envs-help`
3765+
37303766
**--help-js**
37313767

37323768
Show options for ScalaJS
@@ -4378,6 +4414,12 @@ Should include Scala CLI runner on the runtime ClassPath. Runner is added by def
43784414

43794415

43804416

4417+
**--help-envs**
4418+
4419+
Show environment variable help
4420+
4421+
Aliases: `--help-env` ,`--env-help` ,`--envs-help`
4422+
43814423
**--help-js**
43824424

43834425
Show options for ScalaJS
@@ -5036,6 +5078,12 @@ Should include Scala CLI runner on the runtime ClassPath. Runner is added by def
50365078

50375079

50385080

5081+
**--help-envs**
5082+
5083+
Show environment variable help
5084+
5085+
Aliases: `--help-env` ,`--env-help` ,`--envs-help`
5086+
50395087
**--help-js**
50405088

50415089
Show options for ScalaJS
@@ -5959,6 +6007,12 @@ Should include Scala CLI runner on the runtime ClassPath. Runner is added by def
59596007

59606008

59616009

6010+
**--help-envs**
6011+
6012+
Show environment variable help
6013+
6014+
Aliases: `--help-env` ,`--env-help` ,`--envs-help`
6015+
59626016
**--help-js**
59636017

59646018
Show options for ScalaJS

0 commit comments

Comments
 (0)