how to auto-reload changed scala classes into SBT REPL - scala

I am new to Scala and to using emacs + ensime + sbt setup for my Scala development.
This setup is quite nice and light, but there is one thing which drives me nuts - inability to auto-compile / reload changes into Scala console started from sbt.
I use REPL a lot and would like to be able to start REPL from sbt with console command and test my changes to scala classes from REPL without having to close it and reload every time I make a change.
I come from Erlang environment and this way of development is easy with Erlang but seems to be difficult with SBT. I have the JRebel plug-in installed but it doesn't seem to be working for the situation I described.
Has anybody been able to make something similar work and would be willing to share the configuration steps?
Much appreciated in advance.

There are two things possible in sbt:
Causing automatic recompilation of the project sources triggered by a file change by prefixing a command with ~ (tilde). The console, or console-quick, or console-project commands can be prefixed, too, but you have to exit REPL to make the recompilation happen (just hit Ctrl+D and wait.)
Causing automatic execution of REPL commands just after firing the console. They can be defined as properties (e.g. in build.sbt):
initialCommands in console := """
import some.library._
def someFun = println("Hello")
"""
It's not necessary to define the property separately in consoleQuick because it defaults to the one defined in console, but if you would like to use the console-project command you have to define it separately.
On a final note: remember to leave empty line between every property in an *.sbt file. They're necessary to parse the properties correctly. In the example above there are no blank lines in between so it means that everything goes into the initialCommands property (and that's what we want.)

Related

Error when running scala script from terminal; however :load works fine inside interpreter

I am trying to learn Scala, or at least the basics for now.
I went to the scala website to download it from there. I followed the steps and download Coursier and called cs setup and then cs install scala:3.1.1 and cs install scalac:3.1.1.
I started writing simple scripts without classes, like how you'd do in the interpreter. So I opened a text file and wrote print('x') and saved it to filename.scala, then I went to terminal and tried scala filename.scala; however, that gave me the error ("Illegal start of toplevel definition"). I changed the code inside the .scala file to a simple var x : Int 4, and I get a different error ("Error: No main methods detected in script Desktop/filename.scala").
When I open the scala terminal and use the :load option, everything works fine. After looking around SO for a good half an hour, none of the mentioned answers helped. I understand that scala is looking for a full program with objects and methods like java. But from what I read, it should be able to run scripts like the one I wrote by guessing its type. What's the problem? Is this a problem with scala 3 or my terminal? or am I doing something wrong?
Thanks in advance.

Running simple Scala in Intellij

I'm trying to run a very simple hello world Scala program in IntelliJ IDEA on Mac without using the Scala console configuration. I have followed these steps to largely get started, but I didn't set up the debugger outlined there. There isn't a default run configuration enabled, but I can right-click on my source file and select "Scala Console," as we can see here:
Is there a way to select or edit my configurations to make it so I don't have to use the console? Below are the available configurations.
I simply want there to be a way to run my Scala code and see the generated output in the provided console, which Scala Console isn't doing. Thanks for your time.
Lab6 should be an object, not a class.
This will allow you to run it as a main method

Is there any way to fork the SBT console into a new JVM?

For all the reasons listed here:
http://www.scala-sbt.org/0.13/docs/Running-Project-Code.html
it's sometimes necessary to run your Scala code in a separate JVM from the one in which SBT is running. That's also true of the REPL, which you access from the console or test:console commands.
Unfortunately, it doesn't appear that SBT supports running the console in its own JVM (and I'm posting this question here, as requested in the message):
https://groups.google.com/forum/#!topic/simple-build-tool/W0q62PfSIMo
Can someone confirm that this isn't possible and suggest a possible workaround? I'm trying to play with a ScalaFX app in the console, and I have to quit SBT completely each time I run it. It'd be nice to just have to quit the console and keep SBT running.

How do I update Clojure dependencies when working with nrepl.el?

As I understand it, when I do nrepl-jack-in a REPL is loaded along with all the dependencies defined in project.clj. If I then update project.clj to add a new dependency, do I need to kill the server and re-run nrepl-jack-in or is there way to update the dependencies in the current REPL?
Update: Maybe there is some hope,
See https://github.com/cemerick/pomegranate
Previously:
The short answer is yes - you do have to restart the JVM process.
I am aware of no good way to update dependencies in a live repl. Leiningen (called by nrepl-jack-in) will manage dependencies and set up the classpath only upon restarting. Trying to do something dynamic and clever is horribly fragile.
The struck out text below is factually true but upon a moment's reflection seemed such bad advice I have marked it up as such...
If you have a local dependency (e.g. jar file) you might use the long-time deprecated function add-classpath at the repl. But you will be entering the dragon infested swamp of java classloaders.
Restarting the REPL seems to be the simplest way. This can be done
with:
M-x cider-restart
That also appears to accomplish a lein deps. So the whole process
of adding a new dependency simply involves adding the require to
your project.clj and then invoking cider-restart.
Another (very convenient) way is to use
clj-refactor.
Adding the artifact (C-c m a p or cljr-add-project-dependency)
will prompt for the version you want, automatically put the new
dependency into your project.clj file, and reload your session.
Before pomegranate existed, I wrote my own library to dynamically load dependencies.
https://github.com/bmillare/dj
After the release of lein2 and how it under the covers can use pomegrante, I rewrote dj to use this underneath. So, even if you don't use 'dj', it might be a useful as a reference to see what its doing.

sbt custom task using a class in project

How can I add a custom task to sbt build definition that consumes (uses classes, runs methods etc.) the project sources ? It seems it tries to find them before compiling even.
I need to know why you want to call the methods, since this changes the answer. If you want to do something ...
Build related
Want to use class/ methods which do something build related ( minfiy things, uploaded jar/wars to servers, etc..)
you have to put this in a plugin or you need to put the sources in a project folder.
The code cannot be called from your project
If it is build related, someone has probably dealt with a similar problem and there is probably a sbt plugin already, but if not, then let me know and I can explain creating sbt plugins.
Non-build related
Want to just call / test methods which don't have anything to do with the build cycle.
You can put this in an object in your project called Script (name it whatever), start up console and then import script object and run.
To make this even easier you can make a custom import script for the console which imports all scripts automatically, which you can then run
So for example,
package script
object Script {
def foo = println("I am doing things non-build related")
}
in sbt now run
console
>> import script._
>> foo // prints out "I am doing things non-build related"