Configuration
Configuration for scalafmt is defined in a plain text file .scalafmt.conf
using HOCON syntax.
To reuse your configuration with IntelliJ, .scalafmt.conf must be placed in
the root directory of your project.
Here is an example .scalafmt.conf:
align = true // For pretty alignment.
maxColumn = 100 // For my wide 30" display.
A note of warning. I personally use the default style, which means that the default style is by far the most tested and supported style. Most of the configuration flags are quite innocent, while some of them work very differently (esp. Scala.js). It is very difficult to guarantee that all configurations options play nicely together so I recommend you try not to go too crazy on this part.
The following sections describe the most common configuration options.
If you are using scalafmt as a Standalone library, you can pass in a
ScalafmtConfiginstance, which is set toScalafmtStyle.defaultby default.
Most popular
maxColumn
Default: maxColumn = 80
- Keep in mind that 80 characters fit perfectly on a split laptop screen with regular resolution.
- Github mobile view only shows 80 characters and sometimes you might review code on your phone.
- Consider refactoring your code before of choosing a value above 100.
docstrings
Default: docstrings = "ScalaDoc"
/** Align by second asterisk.
*
*/
/** Align by second asterisk.
*
*/
Config for this example
docstrings = ScalaDoc
/** Align by first asterisk.
*
*/
/** Align by first asterisk.
*
*/
Config for this example
docstrings = JavaDoc
assumeStandardLibraryStripMargin
Default: assumeStandardLibraryStripMargin = false
May cause non-idempotent formatting in rare cases, see https://github.com/scalameta/scalafmt/issues/192.
If true, the margin character | is aligned with the opening triple quote
""" in interpolated and raw string literals.
val example1 =
s"""Examples:
| * one
| * two
| * $three
|""".stripMargin
val example1 =
s"""Examples:
| * one
| * two
| * $three
|""".stripMargin
Config for this example
assumeStandardLibraryStripMargin = true
The pipe character can immediately follow the opening """
val example2 =
s"""|Examples:
| * one
| * two
| * $three
|""".stripMargin
val example2 =
s"""|Examples:
| * one
| * two
| * $three
|""".stripMargin
Config for this example
assumeStandardLibraryStripMargin = true
Indentation
continuationIndent.callSite
Default: continuationIndent.callSite = 2
Example:
function(
argument1, // indented by 2
""
)
function(
argument1, // indented by 2
""
)
Config for this example
continuationIndent.defnSite = 2
continuationIndent.defnSite
Default: continuationIndent.defnSite = 4
Same as continuationIndent.callSite except for definition site. Example:
def function(
argument1: Type1 // indented by 4
): ReturnType
def function(
argument1: Type1 // indented by 4
): ReturnType
Config for this example
continuationIndent.defnSite = 4
Alignment
Default: some
Align has several nested fields, which you can customize. However, it comes with four possible defaults: none, some, more, & most.
align
align=none
x match { // false for case arrows
case 2 => 22 // also comments!
case 22 => 222 // don't align me!
}
x match { // false for case arrows
case 2 => 22 // also comments!
case 22 => 222 // don't align me!
}
Config for this example
align = none
Pro tip: Enable this setting to minimize git diffs/conflicts from renamings and other refactorings.
align=some
x match { // true for case arrows
case 2 => 22
case 22 => 222
}
val x = 2 // false for assignment
val xx = 22
case object B extends A // false for `extends`
case object BB extends A
x match { // true for case arrows
case 2 => 22
case 22 => 222
}
val x = 2 // false for assignment
val xx = 22
case object B extends A // false for `extends`
case object BB extends A
Config for this example
align = some
align=more
val x = 2 // true for assignment
val xx = 22
case object B extends A // true for `extends`
case object BB extends A
q -> 22 // true for various infix operators
qq -> 3 // and also comments!
for {
x <- List(1) // true for alignment enumerator
yyy <- List(2)
} yield x ** yyy
x match { // true for multiple tokens across multiple lines
case 1 => 1 -> 2 // first
case 11 => 11 -> 22 // second
// A blank line separates alignment blocks.
case `ignoreMe` => 111 -> 222
}
// Align assignments of similar type.
def name = column[String]("name")
def status = column[Int]("status")
val x = 1
val xx = 22
// Align sbt module IDs.
libraryDependencies ++= Seq(
"org.scala-lang" % "scala-compiler" % scalaVersion.value,
"com.lihaoyi" %% "sourcecode" % "0.1.1"
)
val x = 2 // true for assignment
val xx = 22
case object B extends A // true for `extends`
case object BB extends A
q -> 22 // true for various infix operators
qq -> 3 // and also comments!
for {
x <- List(1) // true for alignment enumerator
yyy <- List(2)
} yield x ** yyy
x match { // true for multiple tokens across multiple lines
case 1 => 1 -> 2 // first
case 11 => 11 -> 22 // second
// A blank line separates alignment blocks.
case `ignoreMe` => 111 -> 222
}
// Align assignments of similar type.
def name = column[String]("name")
def status = column[Int]("status")
val x = 1
val xx = 22
// Align sbt module IDs.
libraryDependencies ++= Seq(
"org.scala-lang" % "scala-compiler" % scalaVersion.value,
"com.lihaoyi" %% "sourcecode" % "0.1.1"
)
Config for this example
align = more
align=most
for {
// align <- with =
x <- List()
yyy = 2
// aligns body by arrow
zzz <- new Integer {
def value = 3
}
} yield x
for {
// align <- with =
x <- List()
yyy = 2
// aligns body by arrow
zzz <- new Integer {
def value = 3
}
} yield x
Config for this example
align = most
Note. Only for the truest vertical aligners. Feel free to open PR enabling more crazy vertical alignment here. Expect changes.
align.tokens
Default: [caseArrow]
An align token is a pair of code, which is the string literal of an operator
of token, and owner, which is the kind of the closest tree node that owns that
token. If no owner is provided, then all tree kinds will be matched.
x match {
case 1 => 1 -> 2
case 11 => 11 -> 22
}
x match {
case 1 => 1 -> 2
case 11 => 11 -> 22
}
Config for this example
align.tokens = [{code = "=>", owner = "Case"}]
val x = List(
"org.scala-lang" %% "scala-compiler" % scalaVersion.value,
"com.lihaoyi" %% "sourcecode" % "0.1.1"
)
val x = List(
"org.scala-lang" %% "scala-compiler" % scalaVersion.value,
"com.lihaoyi" %% "sourcecode" % "0.1.1"
)
Config for this example
align.tokens = [
{code = "%", owner = "Term.ApplyInfix"},
{code = "%%", owner = "Term.ApplyInfix"}
]
To find the owner part for a custom tree, depend on Scalameta and use
scala.meta.Tree.productPrefix from the the (for example, Ammonite) REPL.
@ import $ivy.`org.scalameta:scalameta_2.12:4.0.0-M1`, scala.meta._
@ val termMatch = q"x match { case 2 => foo(bar) }"
termMatch: Term.Match = x match {
case 2 =>
foo(bar)
}
@ termMatch.structure
res0: String = """
Term.Match(Term.Name("x"), Seq(Case(Lit.Int(2), None, Term.Apply(Term.Name("foo"), Seq(Term.Name("bar"))))))
"""
@ termMatch.productPrefix
res1: String = "Term.Match"
align.arrowEnumeratorGenerator
Default: align.arrowEnumeratorGenerator = false
for {
x <- new Integer {
def value = 2
}
} yield x
for {
x <- new Integer {
def value = 2
}
} yield x
Config for this example
align.arrowEnumeratorGenerator = false
for {
x <- new Integer {
def value = 2
}
} yield x
for {
x <- new Integer {
def value = 2
}
} yield x
Config for this example
align.arrowEnumeratorGenerator = true
align.openParenCallSite
Default: align.openParenCallSite = false
foo(arg1, arg2)
function(arg1, // align by (
arg2,
arg3)
function(argument1, argument2)
foo(arg1, arg2)
function(arg1, // align by (
arg2,
arg3)
function(
argument1,
argument2)
Config for this example
align.openParenCallSite = true
foo(arg1, arg2)
function(
arg1, // no align by (
arg2,
arg3
)
function(argument1, argument2)
foo(arg1, arg2)
function(arg1, // no align by (
arg2,
arg3)
function(
argument1,
argument2)
Config for this example
align.openParenCallSite = false
align.openParenDefnSite
Default: align.openParenDefnSite = false
class IntString(int: Int,
string: String)
class IntStringLong(int: Int,
string: String,
long: Long)
class IntString(int: Int, string: String)
class IntStringLong(int: Int,
string: String,
long: Long)
Config for this example
align.openParenDefnSite = true
class IntString(
int: Int,
string: String
)
class IntStringLong(
int: Int,
string: String,
long: Long
)
class IntString(int: Int, string: String)
class IntStringLong(
int: Int,
string: String,
long: Long
)
Config for this example
align.openParenDefnSite = false
Newlines
The newlines.* options are used to configure when and where scalafmt should
insert newlines.
You might be interested in the Vertical Multiline section.
newlines.alwaysBeforeTopLevelStatements
Default: newlines.alwaysBeforeTopLevelStatements = false
import org.scalafmt
package core { // no newline added here
object O { // nor here
val x1 = 1
val x2 = 2
def A = "A"
def B = "B"
}
}
import org.scalafmt
package core { // no newline added here
object O { // nor here
val x1 = 1
val x2 = 2
def A = "A"
def B = "B"
}
}
Config for this example
newlines.alwaysBeforeTopLevelStatements = false
import org.scalafmt
package core {
object O {
val x1 = 1
val x2 = 2
def A = "A"
def B = "B"
}
}
import org.scalafmt
package core {
object O {
val x1 = 1
val x2 = 2
def A = "A"
def B = "B"
}
}
Config for this example
newlines.alwaysBeforeTopLevelStatements = true
newlines.alwaysBeforeElseAfterCurlyIf
Default: newlines.alwaysBeforeElseAfterCurlyIf = false
if (someCond) {
foo()
}
else {
bar()
}
if (someCond) {
foo()
} else {
bar()
}
Config for this example
newlines.alwaysBeforeElseAfterCurlyIf = true
if (someCond) {
foo()
} else {
bar()
}
if (someCond) {
foo()
}
else {
bar()
}
Config for this example
newlines.alwaysBeforeElseAfterCurlyIf = false
Rewrite Rules
To enable a rewrite rule, add it to the config like this
rewrite.rules = [SortImports].
AvoidInfix
a.success(b)
a.error(b, c)
a.map { x =>
x + 2
}
("o" % "a" % "v").c(D)
future
.recover {
case e: Err => 0
}
.map(_.toString)
a success b
a error (b, c)
a map { x =>
x + 2
}
"o" % "a" % "v" c(D)
future recover {
case e: Err => 0
} map (_.toString)
Config for this example
rewrite.rules = [AvoidInfix]
ExpandImportSelectors
import a.b
import a.c
import h.k
import h.l
import d.e.f
import d.e.g
import a.{foo => bar, zzzz => _, _}
import a.{
b,
c
}, h.{
k, l
}
import d.e.{f, g}
import a.{
foo => bar,
zzzz => _,
_
}
Config for this example
rewrite.rules = [ExpandImportSelectors]
RedundantBraces
Warning. This rewrite can cause non-idempotent formatting, see #1055.
def foo =
List(1, 2, 3).sum
def foo = {
List(1, 2, 3).sum
}
Config for this example
rewrite.rules = [RedundantBraces]
q"Hello $name"
q"Hello ${name}"
Config for this example
rewrite.rules = [RedundantBraces]
rewrite.redundantBraces.stringInterpolation = true
Configuration options and default values:
// TODO(olafur): multiline defaults
rewrite.redundantBraces.maxLines = 100rewrite.redundantBraces.includeUnitMethods = truerewrite.redundantBraces.stringInterpolation = truerewrite.redundantBraces.generalExpressions = false(disabled by default due to #1147)
RedundantParens
for {
a <- b
if a.nonEmpty
} yield a
for {
a <- b
if (a.nonEmpty)
} yield a
Config for this example
rewrite.rules = [RedundantParens]
SortModifiers
Modifiers are sorted based on the given order. Affects modifiers of the following definitions: trait, class, object, type, and val+var, both as fields and class parameters.
implicit final private lazy val x = 42
implicit final private lazy val y = 42
final lazy private implicit val x = 42
lazy final implicit private val y = 42
Config for this example
rewrite.rules = [SortModifiers]
class Test(
implicit
final private val i1: Int,
final private val i2: String
)
class Test(
implicit
final private val i1: Int,
private final val i2: String
)
Config for this example
rewrite.rules = [SortModifiers]
sealed protected[X] trait ADT
final private case object A1 extends ADT
final private case class A2(a: Int)
extends ADT
sealed protected[X] trait ADT
final private case object A1 extends ADT
private final case class A2(a: Int)
extends ADT
Config for this example
rewrite.rules = [SortModifiers]
If you choose the non-default sort order then you have to specify all eight modifiers in the order you wish to see them. Hint: since some modifiers are mutually exclusive, you might want to order them next to each other.
implicit final override val x = 2
override implicit final val x = 2
Config for this example
rewrite.rules = [SortModifiers]
rewrite.sortModifiers.order = [
"implicit", "final", "sealed", "abstract",
"override", "private", "protected", "lazy"
]
PreferCurlyFors
Replaces parentheses into curly braces in for comprehensions that contain multiple enumerator generators.
for {
a <- as
b <- bs if b > 2
} yield (a, b)
for(a <- as; b <- bs if b > 2)
yield (a, b)
Config for this example
rewrite.rules = [PreferCurlyFors]
SortImports
The imports are sorted by the groups: symbols, lower-case, upper-case.
import foo.{bar, sand, Random, Zilch}
import foo.{Zilch, bar, Random, sand}
Config for this example
rewrite.rules = [SortImports]
AsciiSortImports
The imports are sorted by their Ascii codes
import foo.{Random, `symbol`, bar, ~>}
import foo.{~>, `symbol`, bar, Random}
Config for this example
rewrite.rules = [AsciiSortImports]
Vertical Multiline
Since: v1.6.0
If enabled this formats methods such that parameters are on their own line
indented by continuationIndent.defnSite.
Separation between parameter groups are indented by two spaces less than
continuationIndent.defnSite. The return type is on its own line at then end.
This formatting is only triggered if the method definition exceeds the maxColumn value in width or if the number of arguments to the method exceeds the
verticalMultiline.arityThreshold.
verticalMultiline.arityThreshold
Default: verticalMultiline.arityThreshold = 100
case class Foo(x: String)
case class Bar(
x: String,
y: String)
object A {
def foo(
x: String,
y: String
)
def hello(
how: String
)(are: String
)(you: String
) = how + are + you
}
case class Foo(x: String)
case class Bar(x: String, y: String)
object A {
def foo(x: String, y: String)
def hello(how: String)(are: String)(you: String) = how + are + you
}
Config for this example
verticalMultiline.atDefnSite = true
verticalMultiline.arityThreshold = 2
verticalMultiline.newlineAfterOpenParen
Default: verticalMultiline.newlineAfterOpenParen = false
def other(
a: String,
b: String
)(
c: String,
d: String
) = a + b + c
def other(a: String, b: String)(c: String, d: String) = a + b + c
Config for this example
continuationIndent.defnSite = 2
verticalMultiline.atDefnSite = true
verticalMultiline.arityThreshold = 2
verticalMultiline.newlineAfterOpenParen = true
verticalMultiline.newlineAfterOpenParen
Default: verticalMultiline.newlineAfterOpenParen = false
def format(
code: String,
age: Int
)(
implicit ev: Parser,
c: Context
): String
def format(code: String, age: Int)(implicit ev: Parser, c: Context): String
Config for this example
maxColumn = 60
verticalMultiline.atDefnSite = true
verticalMultiline.newlineBeforeImplicitKW = true
Disabling Formatting
// format: off
Disable formatting for specific regions of code by wrapping them in
// format: off blocks:
// format: off
val identity = Array(1, 0, 0,
0, 1, 0,
0, 0, 1)
// format: on
// format: off
val identity = Array(1, 0, 0,
0, 1, 0,
0, 0, 1)
// format: on
Project
Configure which source files should be formatted in this project.
# Only format files tracked by git.
project.git = true
# manually exclude files to format.
project.excludeFilters = [
regex1
regex2
]
# manually include files to format.
project.includeFilters = [
regex1
regex2
]
Miscellaneous
binPack.literalArgumentLists
Default: binPack.literalArgumentLists = true
val secret: List[Bit] = List(0, 0, 1, 1,
1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1,
0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0,
1, 0, 0, 0, 1, 0, 1)
val secret: List[Bit] = List(0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 1,
0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1)
Config for this example
binPack.literalArgumentLists = true
val secret: List[Bit] = List(
0,
0,
1,
1,
1,
1,
1,
0,
0,
1,
1,
0,
1
)
val secret: List[Bit] = List(0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1)
Config for this example
binPack.literalArgumentLists = false
includeCurlyBraceInSelectChains
Default: includeCurlyBraceInSelectChains = true
List(1)
.map { x =>
x + 2
}
.filter(_ > 2)
List(1).map { x =>
x + 2
}
.filter(_ > 2)
Config for this example
includeCurlyBraceInSelectChains = true
List(1).map { x =>
x + 2
}.filter(_ > 2)
List(1)
.map { x =>
x + 2
}
.filter(_ > 2)
Config for this example
includeCurlyBraceInSelectChains = false
optIn.breakChainOnFirstMethodDot
Default: optIn.breakChainOnFirstMethodDot = true
// collapse into a single line
foo.map(_ + 1).filter(_ > 2)
// collapse into a single line
foo
.map(_ + 1)
.filter(_ > 2)
Config for this example
optIn.breakChainOnFirstMethodDot = false
foo
.map(_ + 1) // preserve existing newlines
.filter(_ > 2)
foo
.map(_ + 1) // preserve existing newlines
.filter(_ > 2)
Config for this example
optIn.breakChainOnFirstMethodDot = true
Other
To find all available configuration options, it's best to browse the source code
of Scalafmt. A good place to start is ScalafmtConfig. Observe that this
listing below is the top-level, there are more configuration options if you
visited nested fields like spaces and newlines.
version = "1.5.1"
maxColumn = 80
docstrings = ScalaDoc
optIn.configStyleArguments = true
optIn.breaksInsideChains = false
optIn.breakChainOnFirstMethodDot = true
optIn.selfAnnotationNewline = true
optIn.annotationNewlines = true
optIn.blankLineBeforeDocstring = false
binPack.unsafeCallSite = false
binPack.unsafeDefnSite = false
binPack.parentConstructors = false
binPack.literalArgumentLists = true
binPack.literalsMinArgCount = 5
binPack.literalsInclude = [
".*"
]
binPack.literalsExclude = [
String
"Term.Name"
]
continuationIndent.callSite = 2
continuationIndent.defnSite = 4
continuationIndent.extendSite = 4
align.openParenCallSite = false
align.openParenDefnSite = false
align.tokens = [
{
code = "=>"
owner = Case
}
]
align.arrowEnumeratorGenerator = false
align.ifWhileOpenParen = true
align.treeCategory."Defn.Trait" = "class/object/trait"
align.treeCategory."Enumerator.Val" = for
align.treeCategory."Defn.Class" = "class/object/trait"
align.treeCategory."Defn.Object" = "class/object/trait"
align.treeCategory."Defn.Val" = "val/var/def"
align.treeCategory."Defn.Def" = "val/var/def"
align.treeCategory."Defn.Var" = "val/var/def"
align.treeCategory."Enumerator.Generator" = for
spaces.beforeContextBoundColon = Never
spaces.afterTripleEquals = false
spaces.inImportCurlyBraces = false
spaces.inParentheses = false
spaces.neverAroundInfixTypes = []
spaces.afterKeywordBeforeParen = true
spaces.inByNameTypes = true
spaces.afterSymbolicDefs = false
literals.long = Upper
literals.float = Lower
literals.double = Lower
lineEndings = unix
rewrite.rules = []
rewrite.redundantBraces.methodBodies = true
rewrite.redundantBraces.includeUnitMethods = true
rewrite.redundantBraces.maxLines = 100
rewrite.redundantBraces.stringInterpolation = false
rewrite.redundantBraces.generalExpressions = false
rewrite.sortModifiers.order = [
"`implicit`"
"`final`"
"`sealed`"
"`abstract`"
"`override`"
"`private`"
"`protected`"
"`lazy`"
]
rewrite.neverInfix.includeFilters = [
"[\w\d_]+"
]
rewrite.neverInfix.excludeFilters = [
until
to
by
eq
ne
"should.*"
"contain.*"
"must.*"
in
ignore
be
taggedAs
thrownBy
synchronized
have
when
size
only
noneOf
oneElementOf
noElementsOf
atLeastOneElementOf
atMostOneElementOf
allElementsOf
inOrderElementsOf
theSameElementsAs
]
indentOperator.include = ".*"
indentOperator.exclude = "^(&&|\|\|)$"
newlines.neverInResultType = false
newlines.neverBeforeJsNative = false
newlines.sometimesBeforeColonInMethodReturnType = true
newlines.penalizeSingleSelectMultiArgList = true
newlines.alwaysBeforeCurlyBraceLambdaParams = false
newlines.alwaysBeforeTopLevelStatements = false
newlines.afterCurlyLambda = never
newlines.afterImplicitKWInVerticalMultiline = false
newlines.beforeImplicitKWInVerticalMultiline = false
newlines.alwaysBeforeElseAfterCurlyIf = false
newlines.alwaysBeforeMultilineDef = true
runner.debug = false
runner.eventCallback = "<FormatEvent => Unit>"
runner.parser = "<Parse[Tree]>"
runner.optimizer.dequeueOnNewStatements = true
runner.optimizer.escapeInPathologicalCases = true
runner.optimizer.maxVisitsPerToken = 513
runner.optimizer.maxEscapes = 16
runner.optimizer.maxDepth = 100
runner.optimizer.acceptOptimalAtHints = true
runner.optimizer.disableOptimizationsInsideSensitiveAreas = true
runner.optimizer.pruneSlowStates = true
runner.optimizer.recurseOnBlocks = true
runner.optimizer.forceConfigStyleOnOffset = 150
runner.optimizer.forceConfigStyleMinArgCount = 2
runner.maxStateVisits = 1000000
runner.dialect = "<Dialect>"
runner.ignoreWarnings = false
runner.fatalWarnings = false
indentYieldKeyword = true
importSelectors = noBinPack
unindentTopLevelOperators = false
includeCurlyBraceInSelectChains = true
assumeStandardLibraryStripMargin = false
danglingParentheses = true
poorMansTrailingCommasInConfigStyle = false
trailingCommas = never
verticalMultilineAtDefinitionSite = false
verticalMultilineAtDefinitionSiteArityThreshold = 100
verticalMultiline.atDefnSite = false
verticalMultiline.arityThreshold = 100
verticalMultiline.newlineBeforeImplicitKW = false
verticalMultiline.newlineAfterImplicitKW = false
verticalMultiline.newlineAfterOpenParen = false
verticalMultiline.excludeDanglingParens = [
"`class`"
"`trait`"
]
onTestFailure = ""
encoding = "UTF-8"
project.git = false
project.files = []
project.includeFilters = [
".*\.scala$"
".*\.sbt$"
".*\.sc$"
]
project.excludeFilters = []