How to create my own custom scalafmt style that my projects can depend on?
Asked Answered
A

1

6

I have bunch of scala projects. They shall share a common code style. I am using scalafmt to enforce certain rules, yet I have to create a

 .scalafmt.conf

for each project. If the team changes the scalafmt rules, we'd have to change it for each project manually. So the files are prone to evolve on their own.

How can I create a common scalafmt.conf as my own dependency that other project can import? That way, a project could still depend on their own version of the codestyle -- but the upgrade path is much more straight forward and should only contain of upgrade the dependency.

Scalafmt supports default styles like:

 style = default

or

 style  = defaultWithAlign

I am basically looking for a way to define my own style and reference it in my projects:

style = MyCompanyDefault
Apophthegm answered 17/6, 2019 at 8:58 Comment(0)
P
4

Consider defining a custom task to download .scalafmt.conf from remote repository

lazy val remoteScalafmtConfig = taskKey[Unit]("Fetch .scalafmt from external repository")
remoteScalafmtConfig := {
  import scala.sys.process._
  streams.value.log.info("Downloading .scalafmt.conf config from remote repository")
  val remoteScalafmtFile = "https://some/external/repo/.scalafmt.conf"
  val baseDir = (Compile / baseDirectory).value
  url(s"$remoteScalafmtFile") #> (baseDir / ".scalafmt.conf") !
}

and then have compile task depend on remoteProtoFiles task like so

compile in Compile := (compile in Compile).dependsOn(remoteScalafmtConfig).value

Now executing sbt compile should download .scalafmt.conf into project's base directory before compilation executes.

We could create an sbt auto plugin to distribute to each project:

package example

import sbt._
import Keys._

object ScalafmtRemoteConfigPlugin extends AutoPlugin {
  object autoImport {
    lazy val remoteScalafmtConfig = taskKey[Unit]("Fetch .scalafmt from external repository")
  }

  import autoImport._
  override lazy val projectSettings = Seq(
    remoteScalafmtConfig := remoteScalafmtConfigImpl.value,
    compile in Compile := (compile in Compile).dependsOn(remoteScalafmtConfig).value
  )

  lazy val remoteScalafmtConfigImpl = Def.task {
    import scala.sys.process._
    streams.value.log.info("Downloading .scalafmt config from remote repository...")
    val remoteScalafmtFile = "https://github.com/guardian/tip/blob/master/.scalafmt.conf"
    val baseDir = (Compile / baseDirectory).value
    url(s"$remoteScalafmtFile") #> (baseDir / ".scalafmt.conf") !
  }
}

Now importing the plugin in project/plugins.sbt and enabling via enablePlugins(ScalafmtRemoteConfigPlugin) would automatically download .scalafmt after executing sbt compile.

Phytology answered 17/6, 2019 at 9:16 Comment(2)
Would it try to download on each compile run? If yes, it may break early (which can be a good thing) but may break people working offline.Apophthegm
Yes tasks are evaluated each time unlike settings.Phytology

© 2022 - 2024 — McMap. All rights reserved.