emacssbtensime

Executing sbt run in current project with ensime emacs


I have a Scala project called scala-playground and I generated the configuration for Ensime with sbt ensimeConfig and sbt ensimeConfigProject.

When running M-x ensime from a buffer of the project, I can see in the Emacs statusbar that Ensime is connected: it displays Scala[scala-playground].

When running the project with C-c C-b r, a new sbt instance is started in the home directory, a directory in $HOME/project is created and instead of the project directory and fails:

[info] Loading project definition from /home/user/project
[info] Set current project to user (in build file:/home/user/)
[info] sbt server started at 127.0.0.1:4766
sbt:user> 
sbt:user> run
[error] java.lang.RuntimeException: No main class detected.
[error]     at scala.sys.package$.error(package.scala:27)
[error]     at sbt.Defaults$.$anonfun$runTask$4(Defaults.scala:1199)
[error]     at scala.Option.getOrElse(Option.scala:121)
[error]     at sbt.Defaults$.$anonfun$runTask$3(Defaults.scala:1199)
[error]     at sbt.Defaults$.$anonfun$runTask$3$adapted(Defaults.scala:1198)
[error]     at scala.Function1.$anonfun$compose$1(Function1.scala:44)
[error]     at sbt.internal.util.$tilde$greater.$anonfun$$u2219$1(TypeFunctions.scala:42)
[error]     at sbt.std.Transform$$anon$4.work(System.scala:64)
[error]     at sbt.Execute.$anonfun$submit$2(Execute.scala:257)
[error]     at sbt.internal.util.ErrorHandling$.wideConvert(ErrorHandling.scala:17)
[error]     at sbt.Execute.work(Execute.scala:266)
[error]     at sbt.Execute.$anonfun$submit$1(Execute.scala:257)
[error]     at sbt.ConcurrentRestrictions$$anon$4.$anonfun$submitValid$1(ConcurrentRestrictions.scala:167)
[error]     at sbt.CompletionService$$anon$2.call(CompletionService.scala:32)
[error]     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error]     at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511)
[error]     at java.util.concurrent.FutureTask.run(FutureTask.java:266)
[error]     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
[error]     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
[error]     at java.lang.Thread.run(Thread.java:748)
[error] (compile:run) No main class detected.
[error] Total time: 0 s, completed Aug 28, 2017 9:10:03 PM

What is going on?


Solution

  • Short story

    Remove ~/project folder and then start emacs.

    Long story

    If you ever run sbt in your $HOME directory it created basic project structure there, mainly project and target directory. And then if you open any *.scala file emacs (sbt-mode) will go up your path to find root project directory. And it finds one in your $HOME. You can see it in doc's:

    Starting from the current default-directory, find a parent
    directory that is an sbt root. An sbt root directory is
    identified by the following rules:
    
       - a directory containing a 'project/build.properties' in it.
    
       - a directory that contains a file matching one of the patterns
        '*.sbt' or 'project/*.scala' file in it.
    

    One problem with current implementation is fact that this process will be done only once per buffer. If sbt:buffer-project-root variable is set once it will be not updated.

    You can force a new value either by restarting emacs, or by evaluating (setq-local sbt:buffer-project-root nil) per each opened buffer, and then starting sbt form emacs in the usual way.

    If you remove ~/project and run ensime-sbt from any buffer with sbt:buffer-project-root with wrong value, it will start sbt in home, which creates ~/project again. So again, the easiest way is to kill emacs, remove the directory, and then start emacs again.