scala-cli icon indicating copy to clipboard operation
scala-cli copied to clipboard

Show help document if for the invalid subcommand

Open tanishiking opened this issue 1 year ago • 4 comments

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

tanishiking avatar Aug 09 '22 09:08 tanishiking

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.

Gedochao avatar Aug 09 '22 10:08 Gedochao

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 avatar Aug 10 '22 21:08 mpkocher

@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.

Gedochao avatar Aug 11 '22 09:08 Gedochao

@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: 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 implicit run of inputs altogether to mimic scala 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.

mpkocher avatar Aug 23 '22 00:08 mpkocher

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.

Gedochao avatar Dec 06 '22 09:12 Gedochao