Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for initial commands in REPL #604

Closed
lwronski opened this issue Feb 2, 2022 · 26 comments
Closed

Support for initial commands in REPL #604

lwronski opened this issue Feb 2, 2022 · 26 comments
Labels
Community help wanted Issues that idicate features that are nice-to-have but core team does not have time to work on it enhancement New feature or request UX

Comments

@lwronski
Copy link
Contributor

lwronski commented Feb 2, 2022

Is your feature request related to a problem? Please describe.
Support for running initial commands for REPL

Describe the solution you'd like

Adding a flag to specify initial commands. It can be supported in two ways:

  • accept string like this: "import Hello.*"
  • accept *.sc files which should be executed before opening REPL
@alexarchambault
Copy link
Contributor

I'm not sure the Scala 3 REPL allows to specify initial code like this though (might be the same with the Scala 2 one).

@zmerr
Copy link
Contributor

zmerr commented Feb 3, 2022

I am reading the documents for ammonite. It’s just that I don’t understand what initial commands are. Do you want scala-cli to support something like magic imports in ammonite ?

@zmerr
Copy link
Contributor

zmerr commented Feb 3, 2022

You mean something like

scala-cli repl -ic “import Hello.*”
or
scala-cli repl -bo Hello.sc
?

@lwronski
Copy link
Contributor Author

lwronski commented Feb 3, 2022

Hi @zmerr, I thinking about similar feature as in SBT.

Yea, It would be great if Scala CLI could be able to accept both -ic “import Hello.*” and scala-cli repl -bo Hello.sc

@zmerr
Copy link
Contributor

zmerr commented Feb 3, 2022

Hi @lwronski so you mean using those commands for configuring scala-cli to import or open your preferred files in the current execution of repl or some other initial command in the string? Is it what you want me to implement?

@alexarchambault
Copy link
Contributor

alexarchambault commented Feb 3, 2022

Don't know if that's what @lwronski is thinking about, but I think we'd want to use the --predef-code option of Ammonite (which is mentioned on its website). It basically allows to run a bit of code right before the repl session. I guess Scala CLI could accept such code via a flag like… --run-before maybe? or --predef-code like Ammonite?

For *.sc files, maybe we should either read them ourselves, and pass them to Ammonite via --predef-code too, or use Ammonite's --predef option (that accepts paths to *.sc files).

@lwronski
Copy link
Contributor Author

lwronski commented Feb 3, 2022

@zmerr If you run scala-cli repl Hello.scala you have access to Hello object

VL-D-0317:scala-demo lwronski$ scala-cli repl Hello.scala 
Welcome to Scala 3.1.1 (17.0.1, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.
                                                                                
scala> println(Hello.hello)
Hello World

so it would be great if it worked like this:

VL-D-0317:scala-demo lwronski$ scala-cli repl Hello.scala --run-before "import Hello.*"
Welcome to Scala 3.1.1 (17.0.1, Java OpenJDK 64-Bit Server VM).
Type in expressions for evaluation. Or try :help.
                                                                                
scala> println(hello)
Hello World

if that's not possible for Scala 2/3 REPL, then we can add this option only for Ammonite REPL

VL-D-0317:scala-demo lwronski$ scala-cli repl Hello.scala  --ammonite --run-before "import Hello.*"
Welcome to the Ammonite Repl 2.5.1-6-5fce97fb (Scala 3.0.0 Java 17.0.1)
@ println(hello)
Hello World

@zmerr
Copy link
Contributor

zmerr commented Feb 3, 2022

@lwronski Awesome. Now I got what it is that you actually want me to do. I am just curious, why are you still adding Hello.scala to the command, when you are already importing Hello.*? Sorry I am new to this.

@zmerr
Copy link
Contributor

zmerr commented Feb 3, 2022

@lwronski I mean why not this:

scala-cli repl --ammonite --run-before "import Hello.*”

or

scala-cli repl --run-before "import Hello.*”

@lwronski
Copy link
Contributor Author

lwronski commented Feb 4, 2022

If you run REPL without the source files, you have REPL without any loaded classes.

scala-cli repl --ammonite --run-before "import Hello.*” - it doesn't make sense, because there is no exists Hello object.

@zmerr
Copy link
Contributor

zmerr commented Feb 4, 2022

@lwronski thanks. So making it work that way, requires making change to repl as well.

@prolativ
Copy link

In scala 3 if you write your init script like this

export Hello.*

and you run scala-cli repl InitScript.scala
then in REPL you can already directly access everything that was defined in Hello.
Does this solve our problem?
The only thing I can think of that doesn't work out of the box currently is instant execution of side effects from scripts. So even if I write my init script like this

val xxx = println("Hello")

nothing will be printed until I type xxx in the REPL. But maybe that's actually good that starting a REPL doesn't cause any side effects under the hood?

@prolativ
Copy link

I've found one limitation of my solution: wildcard exports work correctly with objects but not with packages.

@bjornregnell
Copy link
Contributor

@prolativ @Gedochao I tried to find among issues in dotty a discussion about export not working for packages. I think it really should, if possible, as I think that feature is very useful. Do you perhaps know where to find any potentially existing discussions about exporting top-level package members also, not just object members? This will allow init repl stuff to be used via scala-cli repl --scala-snippet as discussed in #1853

@prolativ
Copy link

To make things clear: named exports from packages do work - only wildcard exports don't. I assume that's because of complications wildcard imports from packages would bring to incremental compilation. E.g.:

// File1.scala

package pkg1

val x = "a"
// File2.scala

package pkg2

export pkg1.*

Now when this codebase gets compiled and a new file appears:

// File3.scala

package pkg1

val y = "b"

then the compiler would have to figure out that File2.scala has to be recompiled even though none of its dependencies known during the previous compilation has changed. Not to even mention potential cycles of dependencies. In case of objects its much simpler because they're closed - you cannot modify an object without modifying the file in which it's defined or without modifying the sources of its supertypes - but these are already tracked as dependencies transitively

@bjornregnell
Copy link
Contributor

Thanks for the clear explanation @prolativ! So it's a trade-off between being restrictive or risk long compilation times.

I guess my view is that if I introduce wild-card package exports then I want it, even if compilation times get higher. It would be nice though if the compiler or build tool gave me a warning that wildcard exports of packages may trigger a complete re-compilation when new files are added and thus increase compile times.

@prolativ
Copy link

I would say it's not only about longer compilation times but also about correctness of code, unless we give up incremental compilation and compile everything from scratch each time, which is most likely not what we would like in general.

@bjornregnell
Copy link
Contributor

Aha! That makes sense.

@Gedochao
Copy link
Contributor

It seems like most of the benefits of an initial script ran in the beginning of repl is already covered by the export syntax, with package wildcards being the problematic edge case.
It'd be optimal for it to be covered by the compiler, but from what @prolativ wrote, it seems that won't happen (at least not soon).

Still, it'd be great to cover this edge case from Scala CLI's side, which would require supporting an initial script ran at the beginning of repl (which is different from --script-snippet, which adds a script to the repl's classpath).
Unfortunately, it seems we lack the time to do it anytime soon.
Community contribution is welcome, though!

Also, this could be a good argument for spending more time on improving the repl itself - if the repl accepted initial scripts, things would become easy.

@Gedochao Gedochao added enhancement New feature or request UX Community help wanted Issues that idicate features that are nice-to-have but core team does not have time to work on it labels Feb 22, 2023
@bjornregnell
Copy link
Contributor

Thanks for the update @Gedochao ! Yes, ramping up the api of the REPL to make it more versatile would indeed be a nice thing! I think the Scala 3 REPL should have an api that let's it be embedded in an easy way, similar to how the
Scala 2 REPL and also Ammonite for Scala 2 was easy to just instantiate and run things with a simple interpret method call. I had a quick look at the Scala 3 REPL api and it was not obvious how to do this as and I don't understand how to tap into its internal functional State in its current api... So my thumbs up for this!

@tgodzik
Copy link
Member

tgodzik commented Aug 16, 2023

Closing as duplicate of #604 with more recent discussion

@tgodzik tgodzik closed this as completed Aug 16, 2023
@bjornregnell
Copy link
Contributor

Is this a duplicate of itself :) or did you mean to link to another issue? @tgodzik

@tgodzik
Copy link
Member

tgodzik commented Aug 16, 2023

I meant this #2185 😅

@bjornregnell
Copy link
Contributor

bjornregnell commented Feb 12, 2024

I'm not sure this is a duplicate of #2185 ; that issue is (also) about the --interactive option etc.

I think being on feature parity with the sbt setting initialCommands is important, as in:

console / initialCommands := """import stuff.*"""

The above works also for Scala 3.

The use case is to prevent tedious re-typing of lot's of imports in every repl session.

Should I open another issue or should we re-open this? I think it is important that this use case is not "forgotten".

Also it might be easier to solve allowing pre-REPL import rather than supporting all the stuff discussed in #2185 so a seperate issue for the import use-case might make sense?

@Gedochao
Copy link
Contributor

Should I open another issue or should we re-open this? I think it is important that this use case is not "forgotten".

Also it might be easier to solve allowing pre-REPL import rather than supporting all the stuff discussed in #2185 so a seperate issue for the import use-case might make sense?

Agreed, I think a new issue makes sense, given the number of different things that were discussed here and in #2185.

@bjornregnell
Copy link
Contributor

OK I'll make a new issue soon and link to the other issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Community help wanted Issues that idicate features that are nice-to-have but core team does not have time to work on it enhancement New feature or request UX
Projects
None yet
Development

No branches or pull requests

7 participants