Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

scala

scalafmt

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
like image 431
k0pernikus Avatar asked Oct 15 '22 14:10

k0pernikus


1 Answers

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.

like image 106
Mario Galic Avatar answered Oct 26 '22 22:10

Mario Galic