scalameta / metals-feature-requests

Issue tracker for Metals feature requests
37 stars 4 forks source link

A simple mechanism for parameters for a Scala app #345

Open carlca opened 1 year ago

carlca commented 1 year ago

I've just started working with Scala and Metals in VSCode. I was delighted to notice the Run and Debug hints showing up in the code, apparently without any need to specify debug ports and the like, in launch.json.

It occurred to, though that there is no way to specify command-line parameters. If one tried to use the Args feature of the launch.json it doesn't get passed though to Metals.

Can I propose, therefore, a folder beneath where the source files reside, called, maybe, .params or .args, and in there, with a 1 to 1 relationship with the source files, files such as app1.json to correspond to app1.scala in the parent directory, with contents of, say...

{
  "params": 
    [
      "alpha",
      "beta',
      "gamma"
     ]
}

These parameters would then be passed forward to the app to be processed by a main function in the usual Scala manner.

This approach would have the advantage of being much more light-weight than a UI based solution and still be very usable in terms of workflow, the key thing being that once it was setup, it wouldn't need changing again, unless the aims of the program changed.

Search terms

parameters param args

adpi2 commented 1 year ago

It occurred to, though that there is no way to specify command-line parameters. If one tried to use the Args feature of the launch.json it doesn't get passed though to Metals.

If you configure your launch.json file correctly, it should pass the args to the Scala app. Otherwise it is a bug and it should be reported in https://github.com/scalameta/metals.

The documentation on how to configure the launch.json is here: https://scalameta.org/metals/docs/editors/vscode/#via-a-launchjson-configuration

carlca commented 1 year ago

I have the situation where I am learning Scala via "Programming Scala 3" by Dean Wampler. This has a large set of example code files, all set up under one large project. I'm trying to avoid as much unnecessary typing as possible, so I don't really want to be editing lots of launch.jsons for al the different source files, and besides, where do the 'launch.json files for individual .scala files go? I had already resigned my self to having to set the params per source file, if a solution could be found, but this would surely be a smaller subset of the total number of source file.

adpi2 commented 1 year ago

so I don't really want to be editing lots of launch.jsons for al the different source files, and besides, where do the 'launch.json files for individual .scala files go?

There is a single launch.json file that should be in the .vscode folder. It can contain as many launch configurations as you want, one for each code example.

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "scala",
      "request": "launch",
      "name": "Launch Main1",
      "mainClass": "com.example.Main1",
      "args": ["foo", "bar"]
    },
    {
      "type": "scala",
      "request": "launch",
      "name": "Launch Main2",
      "mainClass": "com.example.Main2",
      "args": ["fizz", "buzz"]
    }
  ]
}

Alternatively you stay in your Scala files and define your own main method that redirect to the "official" one with arguments:

@main def example1WithArgs(): Unit =
  example1(Array("foo", "bar"))

if a solution could be found

The current design of the launch.json is driven by VS Code. It is not specific to Metals or Scala. Whether we can improve it or not depends on what's supported and recommended by VS Code.

tgodzik commented 1 year ago

I wonder if we could automatically create launch.json entries for anything that was run (and if that is desired) or alternatively add another lens for that :thinking:

We could also in some cases automatically add for parameters (for example with the @main annotation we would know the exact number of them)

carlca commented 1 year ago

so I don't really want to be editing lots of launch.jsons for al the different source files, and besides, where do the 'launch.json files for individual .scala files go?

There is a single launch.json file that should be in the .vscode folder. It can contain as many launch configurations as you want, one for each code example.

The problem is that in the situation I'm describing, there is one project containing many executable .scala files in many sub-directories. The advantage of the Run and Debug hints, is that the code can be run or debugged with zero configuration.

SCR-20230615-sqqz

Can you confirm that Metals is responsible for the Run and Debug hints?

Anyhow, the Run and Debug links to not appear to be governed by the launch.json, as shown by the fact that debugging is still possible even if no launch.json is present.

Alternatively you stay in your Scala files and define your own main method that redirect to the "official" one with arguments:

@main def example1WithArgs(): Unit =
  example1(Array("foo", "bar"))

That's what I have been having to do. It gets very tedious very quickly!

carlca commented 1 year ago

I wonder if we could automatically create launch.json entries for anything that was run (and if that is desired) or alternatively add another lens for that 🤔

We could also in some cases automatically add for parameters (for example with the @main annotation we would know the exact number of them)

This sounds interesting! Anything that combines the ease of use of the Debug link (see image in other reply) and the ability to pass in parameters on a per-scala file basis but without using launch.json is what I think I'm after here...

tgodzik commented 1 year ago

It should be easy to parse the main method and get the parameters, though it might need some tinkering when running via task view.

ckipp01 commented 1 year ago

I have no idea if this is possible in VS Code or not, but one of the things you can do with nvim-metals is make a configuration that takes in user input when it's triggered. For example it looks like this:

2023-06-16 08 46 01

Which just triggers the user for the input before it goes back to Metals. This could also be a way to allow for users to provide that input dynamically.