Scala 3 has a new “quiet” syntax, which means it uses whitespace and indention to delineate blocks of code, instead of the parentheses. Currently emacs-scala-mode does not support this yet fully, and while it is in the works the quick solution is to turn of automatic indention for scala 3 projects. To achieve this two things are required, it needs to be detected that a scala file is part of a scala 3 project, and second the automatic indention and reformatting needs to be turned off.
A quick, and somewhat hacky, way to detect scala 3 projects is to check the build.sbt
file for the version, using projectile to find the root of the project and searching for a scalaVersion
to start with 3.
(defun is-scala3-project ()
"Check if the current project is using scala3.
Loads the build.sbt file for the project and serach for the scalaVersion."
(projectile-with-default-dir (projectile-project-root)
(when (file-exists-p "build.sbt")
(with-temp-buffer
(insert-file-contents "build.sbt")
(search-forward "scalaVersion := \"3" nil t)))))
Now using emacs advice-add
the function adding the hooks to indent and format can be modified to no longer no longer insert the hooks for automatic formatting
(defun with-disable-for-scala3 (orig-scala-mode-map:add-self-insert-hooks &rest arguments)
"When using scala3 skip adding indention hooks."
(unless (is-scala3-project)
(apply orig-scala-mode-map:add-self-insert-hooks arguments)))
(advice-add #'scala-mode-map:add-self-insert-hooks :around #'with-disable-for-scala3)
To still have some indention but not use the scala syntax specific one, the indent-line-function
needs to be replaced with one purely using the previous line for reference ignoring syntax.
(defun disable-scala-indent ()
"In scala 3 indent line does not work as expected due to whitespace grammar."
(when (is-scala3-project)
(setq indent-line-function 'indent-relative-maybe)))
(add-hook 'scala-mode-hook #'disable-scala-indent)
While it is more convenient to have indention supported, while the issue in emacs-scala-mode is being worked on this provides a quick fix to still have scala 3 code formatted. Also with metals and lsp supporting scala 3, the buffer can be reformatted in case formatting is an issue.