VirtusLab / scala-cli

Scala CLI is a command-line tool to interact with the Scala language. It lets you compile, run, test, and package your Scala code (and more!)
https://scala-cli.virtuslab.org
Apache License 2.0
542 stars 128 forks source link

Output of `scala run --help` is unclear #1669

Closed julienrf closed 1 year ago

julienrf commented 1 year ago

Is your feature request related to a problem? Please describe.

Running scala run --help (with scala installed via cs install scala-experimental) does not explain how the program is executed. Furthermore, it shows a lot of options that should probably stay in incubation in Scala CLI for some time.

$ scala run --help 
Usage: /home/julien/.local/share/coursier/bin/.scala.aux run [options]
Compile and run Scala code.

To pass arguments to the application, just add them after `--`, like:

```sh
scala-cli MyApp.scala -- first-arg second-arg
```

Help options:
  --usage                                        Print usage and exit
  -h, -help, --help                              Print help message and exit
  -help-full, -full-help, --help-full, --full-help  Print help message, including hidden options, and exit

Scala options:
  --js                                           Enable Scala.js. To show more options for Scala.js pass `--help-js`
  --native                                       Enable Scala Native. To show more options for Scala Native pass `--help-native`
  -P, --plugin, --compiler-plugin string*        Add compiler plugin dependencies
  -O, --scala-opt, --scala-option, --scalac-option option  Add a `scalac` option. Note that options starting with `-g`, `-language`, `-opt`, `-P`, `-target`, `-V`, `-W`, `-X`, and `-Y` are assumed to be Scala compiler options and don't require to be passed after `-O` or `--scalac-option`.
  -S, --scala, --scala-version version           Set the Scala version (3.2.1 by default)
  --scalac-help, --help-scalac                   Show help for scalac. This is an alias for --scalac-option -help
  --scalac-verbose, --verbose-scalac             Turn verbosity on for scalac. This is an alias for --scalac-option -verbose
  --script-snippet string*                       Allows to execute a passed string as a Scala script
  --scala-snippet string*                        Allows to execute a passed string as Scala code

Java options:
  --java-home path                               Set the Java home directory
  -j, --jvm jvm-name                             Use a specific JVM, such as `14`, `adopt:11`, or `graalvm:21`, or `system`
  --java-snippet string*                         Allows to execute a passed string as Java code
  --execute-java string*                         A synonym to --scala-snippet, which defaults the sub-command to `run` when no sub-command is passed explicitly
  -cp, --jar, --jars, --class, --classes, -classpath, --classpath, --extra-jar, --extra-jars, --class-path, --extra-class, --extra-classes, --extra-class-path paths  Add extra JARs and compiled classes to the class path
  --compile-only-jar, --compile-only-jars, --extra-compile-only-jar, --extra-compile-only-jars paths  Add extra JARs in the compilaion class path. Mainly using to run code in managed environments like Spark not to include certain depenencies on runtime ClassPath.
  --source-jar, --source-jars, --extra-source-jar, --extra-source-jars paths  Add extra source JARs
  --resource-dir, --resource-dirs paths          Add a resource directory
  -J, --java-opt java-options                    Set Java options, such as `-Xmx1g`
  --java-prop key=value|key                      Set Java properties

Logging options:
  -v, --verbose  Increase verbosity (can be specified multiple times)
  -q, --quiet    Decrease verbosity
  --progress     Use progress bars

Entrypoint options:
  -M, --main-class main-class                    Specify which main class to run
  --main-class-ls, --list-main-class, --main-class-list, --list-main-classes  List main classes available in the current context

Debug options:
  --debug                         Turn debugging on
  --debug-port string?            Debug port (5005 by default)
  --debug-mode attach|a|listen|l  Debug mode (attach by default)

Compilation server options:
  --server  Enable / disable usage of Bloop compilation server. Bloop is used by default so use `--server=false` to disable it. Disabling compilation server allows to test compilation in more controlled mannter (no caching or incremental compiler) but has a detrimental effect of performance.

Run options:
  --standalone-spark, --spark-standalone  Run as a Spark job, using a vanilla Spark distribution downloaded by Scala CLI
  --hadoop, --hadoop-jar                  Run as a Hadoop job, using the "hadoop jar" command
  --command                               Print the command that would have been run (one argument per line), rather than running it
  --scratch-dir string?                   Temporary / working directory where to write generated launchers

Benchmarking options:
  --jmh                  Run JMH benchmarks
  --jmh-version version  Set JMH version

Markdown options:
  --md-snippet, --markdown-snippet string*  [experimental] Allows to execute a passed string as Markdown code
  --md, --markdown, --enable-markdown       Enable markdown support.

Dependency options:
  --dep, --dependency string*       Add dependencies
  -r, --repo, --repository string*  Add repositories

Other options:
  -i, --interactive                              Interactive mode
  --actions                                      Enable actionable diagnostics
  --home, --home-directory string?               Override the path to user's home directory
  --python-setup                                 Set Java options so that Python can be loaded
  --py, --python                                 Enable Python support via ScalaPy
  --scalapy-version, --scala-py-version string?  [experimental] Set ScalaPy version (0.5.2+5-83f1eb68 by default)
  --platform scala-js|scala-native|jvm           Specify platform
  --help-js                                      Show options for ScalaJS
  --help-native                                  Show options for ScalaNative
  --help-doc, --doc-help, --help-scaladoc, --scaladoc-help  Show options for Scaladoc
  --help-repl, --repl-help                       Show options for Scala REPL
  --help-fmt, --fmt-help, --help-scalafmt, --scalafmt-help  Show options for Scalafmt
  -d, --compile-out, --destination, --compile-output, --output-directory, --compilation-output /example/path  Copy compilation results to output directory using either relative or absolute path
  -w, --watch                                    Watch source files for changes
  --restart, --revolver                          Run your application in background and automatically restart if sources have been changed
  --cross                                        Run given command against all provided Scala versions and/or platforms

Describe the solution you'd like

I think a good start would be to explain better what it means to run the program (see also the discussion https://github.com/VirtusLab/scala-cli/discussions/1668 about the types of programs that we want to support), and which platforms (JVM, JS, native) are supported.

All the options should be documented more clearly. For instance, the description of the --watch option is too short. We should say that the program will be run again on every file change. But then the difference with --restart is not clear. Is scala run --restart foo.scala equivalent to scala run --watch foo.scala &? How does file watching work when the program uses multiple files? Please clarify all these details in the documentation.

I am not sure the following options should be part of the stable scala (unless you are very confident that they don’t require any maintenance effort, that the command-line interface is stable, and that they work extremely reliably?):

tgodzik commented 1 year ago

Thanks for reporting! I think we shouldn't report the experimental/scala-cli only options in scala runner, seems like a bug.

does not explain how the program is executed

Not sure I understand, wouldn't it be a internal thing that users shouldn't need to know about?

All the options should be documented more clearly. For instance, the description of the --watch option is too short. We should say that the program will be run again on every file change. But then the difference with --restart is not clear. Is scala run --restart foo.scala equivalent to scala run --watch foo.scala &? How does file watching work when the program uses multiple files? Please clarify all these details in the documentation.

Good points! We'll try to clarify that!

julienrf commented 1 year ago

does not explain how the program is executed

Not sure I understand, wouldn't it be a internal thing that users shouldn't need to know about?

There is a part of it that is internal details and that part should not be exposed in the documentation. But as a user, I need to know what types of programs Scala CLI accepts. Do I need to write a “main method”? Can I use multiple files? Can configure the compiler (version and options) in the source code? Can I use third-party dependencies? If I use the Scala.js platform, do I have to set up Node.js myself? Are there any other requirements I should be aware of? Some of this information is available somewhere else (e.g. in the documentation of the --dependency option) but I think it would be useful to remind the general behavior of the run command in the first paragraph. It could be useful to put a link to the website also, in case we want to show only a summary here, and more details on the website.

tgodzik commented 1 year ago

Ok, thanks for explaining!

Gedochao commented 1 year ago

@julienrf would a summary like this be sufficient? not sure if the help isn't getting too verbose like this...


▶ scala-prototype -help
Usage: /Users/pchabelski/IdeaProjects/scala-cli/out/cli/base-image/nativeImage.dest/scala <COMMAND>
Scala code runner is a command-line tool to interact with the Scala language. It lets you compile, run and test your Scala code.

The tool will use Java 17+ if found on PATH, otherwise the appropriate Java version will be downloaded automatically.
Arguments are generally treated as inputs in most sub-commands (with some exceptions, like the shebang sub-command).
Inputs can be .scala, .java and other files with supported extensions, as well as directories, URL addresses or other virtual sources.
Using directives can be used in all supported inputs.
External dependencies can be specified with the --dependency option or the using lib directive.
Default configurations are assumed for things like the Scala language version. (current default: 3.2.1)

Detailed documentation can be found on our website: https://scala-cli.virtuslab.org

Main commands:
  clean                  Clean the workspace
  compile                Compile Scala code
  doc                    Generate Scaladoc documentation
  fmt, format, scalafmt  Format Scala code
  repl, console          Fire-up a Scala REPL
  run                    Compile and run Scala code. A main class has to be present.
  test                   Compile and test Scala code

Miscellaneous commands:
  about    Print details about this application
  version  Print version

Other commands:
  help                                          Print help message
  install completions, install-completions      Installs completions into your shell
  setup-ide                                     Generate a BSP file that you can import into your IDE
  shebang                                       Like `run`, but more handy from shebang scripts
  uninstall                                     Uninstall scala-cli - only works when installed by the installation script
  uninstall completions, uninstall-completions  Uninstalls completions from your shell
  update                                        Update scala-cli - only works when installed by the installation script

Doctor commands:
  doctor  Print details about this application

See 'scala <command> --help' to read about a specific subcommand. To see full help run 'scala <command> --help-full'.
To run another Scala code runner version, specify it with '--cli-version' before any other argument, like 'scala --cli-version <version> args'.

When no subcommand is passed explicitly, an implicit subcommand is used based on context:
  - if the '--version' option is passed, it prints the 'version' subcommand output, unmodified by any other options
  - if any inputs were passed, it defaults to the 'run' subcommand
  - additionally, when no inputs were passed, it defaults to the 'run' subcommand in the following scenarios:
    - if a snippet was passed with any of the '--execute*' options
    - 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

I think it's fair to explain to the user about some of the absolute basics for working with the tool, instead of sending him straight to the docs website... but then, we'd like to avoid walls of text after -help is called. So I'm trying to find some middle ground (and even the attempt above feels slightly wordy to me, tbh...)

julienrf commented 1 year ago

Thank you for working on this!

I have a first question: the issue was about the output of scala run --help, but it seems that your comment is about scala --help. Should the output be the same? I don’t think so. In the case of scala --help we should first explain the concept of subcommands (and that more detailed documentation can be found by running scala <command> --help), and then explain the logic for picking a default subcommand if none is explicitly passed.

Let me react on some specific parts of the first paragraph:

The tool will use Java 17+ if found on PATH, otherwise the appropriate Java version will be downloaded automatically.

Does that apply to every subcommand?

Arguments are generally treated as inputs in most sub-commands (with some exceptions, like the shebang sub-command). Inputs can be .scala, .java and other files with supported extensions, as well as directories, URL addresses or other virtual sources. Using directives can be used in all supported inputs. External dependencies can be specified with the --dependency option or the using lib directive. Default configurations are assumed for things like the Scala language version. (current default: 3.2.1)

I think this information is not really useful here because its applicability depends on which subcommand is used. I would consider instead adding it to the specific help of the relevant subcommands.

Gedochao commented 1 year ago

I have a first question: the issue was about the output of scala run --help, but it seems that your comment is about scala --help. Should the output be the same?

Yeah, it shouldn't. I somehow got confused and assumed this ticket is about the default sub-command help, my bad 😅

So we should expand on individual subcommands usage explanations in their respective -help. Yeah, that makes more sense.