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.