scala-cli
scala-cli copied to clipboard
Show help document if for the invalid subcommand
Is your feature request related to a problem? Please describe.
If I provide an invalid subcommand to scala-cli
, it shows a stacktrace.
$ ❯ scala-cli invalid
scala.build.errors.InputsException: invalid: not found
scala.build.Inputs$.forNonEmptyArgs(Inputs.scala:436)
scala.build.Inputs$.apply(Inputs.scala:471)
scala.cli.commands.util.SharedOptionsUtil$SharedOptionsOps.inputs(SharedOptionsUtil.scala:276)
scala.cli.commands.util.SharedOptionsUtil$SharedOptionsOps.inputsOrExit(SharedOptionsUtil.scala:231)
scala.cli.commands.Run$.run(Run.scala:64)
scala.cli.commands.Run$.run(Run.scala:34)
scala.cli.commands.Default.run(Default.scala:37)
scala.cli.commands.Default.run(Default.scala:30)
caseapp.core.app.CaseApp.main(CaseApp.scala:149)
caseapp.core.app.CommandsEntryPoint.main(CommandsEntryPoint.scala:120)
scala.cli.ScalaCliCommands.main(ScalaCliCommands.scala:119)
scala.cli.ScalaCli$.main0(ScalaCli.scala:184)
scala.cli.ScalaCli$.main(ScalaCli.scala:83)
scala.cli.ScalaCli.main(ScalaCli.scala)
Describe the solution you'd like
It would be helpful if scala-cli
shows a help document (that is shown when we type scala-cli help
) when we provide an invalid subcommand
$ scala-cli invalid
'invalid' is not a scala-cli command <- something like that
Usage: scala-cli <COMMAND>
Scala CLI is a command-line tool to interact with the Scala language. It lets you compile, run, test, and package your Scala code.
Other commands:
export Export current project to sbt or Mill
help Print help message
install completions, install-completions Installs completions into your shell
...
Describe alternatives you've considered
It might be better to show a small error message that recommends users to run scala-cli help
.
For example, git command shows the following message for invalid command.
$ git invalid
git: 'invalid' is not a git command. See 'git --help'.
Additional context none
Hey, good point. ~~And it should be simple enough to do that, too.~~
EDIT: On second thought, I wonder. when running the following:
scala-cli invalid
Scala CLI looks for defined sub-commands and figures invalid
is not one of them.
And then it actually defaults to running the run
command and takes any args coming afterwards accordingly.
So,
scala-cli Main.scala
is actually the equivalent of
scala-cli run Main.scala
This is why the exception you are receiving is an InputsException
- Scala CLI figures invalid
is not a sub-command, so tries to use invalid
as an input for the run
sub-command - and then fails, since such a file does not exist. But - ./invalid
could theoretically be an actual file.
Now, I agree that better error handling and an informative error message would be in place, but one needs to keep this context in mind.
This implicit dispatching mechanism to run
perhaps creates fundamental friction points and ambiguities.
For example, having a project in a dir called test
won't work as expected and will have confusing output.
❯❯❯ cat test/Example.scala
object Hello {
def main(args: Array[String]): Unit =
println("Hello from Scala")
}
❯❯❯ scala-cli test # this should run my project
[error] No inputs provided (expected files with .scala or .sc extensions, and / or directories).
❯❯❯ scala-cli run test
Hello from Scala
❯❯❯ scala-cli test test
No test framework found
For every subcommand (e.g., help
, package
, github
, etc...) this is a potential issue of conflict with directory/project names.
I suspect the motivation for this implicit dispatching design is to mimic the scala
behavior. However, it's a bit different, scala
has -howtorun
flag.
I somewhat understand the motivation for this implicit dispatch model, however, I'm not sure it really adds enough value versus an explicit call to the subcommand (e.g., scala-cli run
, scala-cli compile
).
Also, for a data point, when I started using scala-cli
, I (incorrectly) assumed that scala-cli Example.scala
was compiling, not running the project/code (specifically in the context of pointing to a gist URL). After consulting the docs, the behavior of run
was clarified.
@mpkocher it is currently likely that the implicit dispatching mechanism to the run
sub-command might be swapped out in for of the repl
sub-command in the near future. Relevant SIP discussion: https://github.com/scala/improvement-proposals/pull/46#discussion_r925787060
I am not yet sure if that'd mean only running scala-cli
with no input args would default to the repl, or would we scrap the implicit run
of inputs altogether to mimic scala
better.
So the TL;DR is, let's hold our horses for a bit with this. The exception handling proposed by @tanishiking definitely still applies, but we should keep the above in mind when improving anything surrounding it.
@mpkocher it is currently likely that the implicit dispatching mechanism to the
run
sub-command might be swapped out in for of therepl
sub-command in the near future. Relevant SIP discussion: scala/improvement-proposals#46 (comment)I am not yet sure if that'd mean only running
scala-cli
with no input args would default to the repl, or would we scrap the implicitrun
of inputs altogether to mimicscala
better.
The scala-cli repl
subcommand accepts positional args and has the same interface as scala-cli run
. Doesn't changing the auto dispatch from run
to repl
have the same potential name collision issue? Or the "root" level repl call would be slightly different than scala-cli repl
? I'm not sure this would be a good idea. It's also hard to clearly communicate this behavior in the root level --help
.
The current behaviour of scala-cli
when a sub-command is not passed explicitly can be found in the docs.
This ticket should cover the following:
- when an invalid argument with no file extension is passed as the first argument to
scala-cli
(it is not a valid directory in the current working directory), a meaningful error should be shown along with the output of the help command - all other invalid inputs (including non-existent directories passed as the second and later args) should produce meaningful errors indicating they were treated as inputs Current behaviour:
▶ scala-cli invalid
[error] invalid: not found
Example desired behaviours:
- Ambiguous invalid sub-command or directory passed as the first arg (help is shown after the error)
▶ scala-cli invalid
[error] 'invalid' is not a scala-cli sub-command, and it is not a valid path to an inputs directory, either.
Usage: scala-cli <COMMAND>
Scala CLI is a command-line tool to interact with the Scala language.
(...)
- Invalid directory passed as a later arg:
▶ scala-cli ValidInput.scala invalid
[error] 'invalid' is not a valid path to an input.
- Invalid input with an extension as the first arg (the file extension makes it clear that it wasn't meant as a subcommand).
▶ scala-cli InvalidInput.scala
[error] 'InvalidInput.scala' is not a valid path to an input.
Invalid remote args (i.e. invalid URLs) should not be handled as part of this ticket.