Configuration
Configuration for scalafmt is defined in a plain text file .scalafmt.conf
using HOCON syntax.
Here is an example .scalafmt.conf
:
align.preset = more // For pretty alignment.
maxColumn = 100 // For my wide 30" display.
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.
assumeStandardLibraryStripMargin
This parameter simply says the .stripMargin
method was not redefined by the
user to assign special meaning to indentation preceding the |
character.
Hence, that indentation can be modified.
# Defaults
assumeStandardLibraryStripMargin = false
align.stripMargin = true
If true
, lines starting with the margin character |
(or another if specified
in the .stripMargin(...)
call) will be indented differently.
If align.stripMargin
is true, they will align with the opening triple-quote
"""
in interpolated and raw string literals. Otherwise, they will be indented
relative to the start of the opening line.
val example1 =
s"""Examples:
| * one
| * two
| * $three
|""".stripMargin
val example1 =
s"""Examples:
| * one
| * two
| * $three
|""".stripMargin
Config for this example:
assumeStandardLibraryStripMargin = true
align.stripMargin = true
val example1 =
s"""|Examples:
| * one
| * two
| * $three
|""".stripMargin
val example1 =
s"""|Examples:
| * one
| * two
| * $three
|""".stripMargin
Config for this example:
assumeStandardLibraryStripMargin = true
align.stripMargin = false
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
align.stripMargin = true
Presets
Some sections provide preset values to set multiple parameters at once. These
are always accessed via the preset
key of the appropriate section, including
top-level.
Top-level presets
preset=default
: this preset is implicit and sets all values to their defaults.preset=IntelliJ
: this preset is defined as
preset = default
continuationIndent.defnSite = 2
optIn.configStyleArguments = false
preset=defaultWithAlign
: this preset is defined as
preset = default
align.preset = more
preset=Scala.js
: this preset is defined as
preset = default
binPack.preset = true
align.ifWhileOpenParen = false
continuationIndent.callSite = 4
docstrings.style = Asterisk
importSelectors = binPack
newlines {
neverInResultType = true
neverBeforeJsNative = true
sometimesBeforeColonInMethodReturnType = false
}
runner.optimizer {
forceConfigStyleOnOffset = 500
forceConfigStyleMinArgCount = 5
}
Indentation
continuationIndent.callSite
Default: continuationIndent.callSite = 2
Example:
function(
argument1, // indented by 2
""
)
function(
argument1, // indented by 2
""
)
Config for this example:
continuationIndent.callSite = 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
continuationIndent.ctorSite
Since v2.5.0.
Applies to constructors. Defaults to continuationIndent.defnSite
.
class A(
field1: Type1 // indented by 4
) {
def function2(
argument1: Type1 // indented by 2
): ReturnType = None
}
class A(
field1: Type1 // indented by 4
) {
def function2(
argument1: Type1 // indented by 2
): ReturnType = None
}
Config for this example:
continuationIndent.ctorSite = 4
continuationIndent.defnSite = 2
continuationIndent.caseSite
Since v3.0.0.
Applies indentation to case values before arrow.
Default: continuationIndent.caseSite = 4
x match {
case _: Aaaaaa |
_: Bbbbbb |
_: Cccccc =>
}
x match {
case _: Aaaaaa |
_: Bbbbbb |
_: Cccccc =>
}
Config for this example:
maxColumn = 20
continuationIndent.caseSite = 5
continuationIndent.extendSite
# Defaults
continuationIndent.extendSite = 4
continuationIndent.withSiteRelativeToExtends = 0
trait Foo
extends A
with B
with C
with D
with E {
def foo: Boolean = true
}
trait Foo extends A with B with C with D with E {
def foo: Boolean = true
}
Config for this example:
continuationIndent.extendSite = 4
# this one added in v2.5.0
continuationIndent.withSiteRelativeToExtends = 2
maxColumn = 30
continuationIndent.commaSiteRelativeToExtends
Since v3.0.0
Added to support Scala 3, which allows to specify multiple parents with a comma.
# Defaults
continuationIndent.extendSite = 4
continuationIndent.commaSiteRelativeToExtends = 2
trait Foo
extends A,
B,
C,
D,
E {
def foo: Boolean =
true
}
trait Foo extends A, B, C, D, E {
def foo: Boolean = true
}
Config for this example:
runner.dialect = scala3
continuationIndent.extendSite = 4
continuationIndent.commaSiteRelativeToExtends = 4
maxColumn = 20
indentOperator
Normally, the first eligible break inside a chain of infix operators is indented by 2.
This group of parameters allows overriding which infix operators are eligible and controls when indentation is omitted.
indentOperator.topLevelOnly
If true, only top-level infix operators are eligible to be exempted from the default indentation rule.
Default: indentOperator.topLevelOnly = true
function(
a &&
b
)
function {
a &&
b
}
function(
a &&
b
)
function {
a &&
b
}
Config for this example:
indentOperator.topLevelOnly = true
function(
a &&
b
)
function {
a &&
b
}
function(
a &&
b
)
function {
a &&
b
}
Config for this example:
indentOperator.topLevelOnly = false
indentOperator.exclude
Defines a regular expression for excluded infix operators. If an eligible operator matches, it will not be indented.
Default: indentOperator.exclude = "^(&&|\\|\\|)$"
indentOperator.include
Defines a regular expression for included infix operators. If an eligible operator matches and is not excluded explicitly by indentOperator.exclude, it be will indented.
Default: indentOperator.include = ".*"
indentOperator.preset
default
- use defaults for all fields
spray
(alsoakka
)- set
include = "^.*=$"
,exclude = "^$"
- set
Alignment
Default: some
Align has several nested fields, which you can customize. However, it comes with four possible presets: none, some, more, & most.
align
align.preset=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.preset = none
Pro tip: Enable this setting to minimize git diffs/conflicts from renamings and other refactorings, without having to ignore whitespace changes in diffs or use
--ignore-all-space
to avoid conflicts when git merging or rebasing.
Starting with the introduction of
align.stripMargin
parameter in v2.5.0, one must explicitly enable it to get earlier behaviour ofalign.preset=none
. See assumeStandardLibraryStripMargin.
align.preset=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.preset = some
align.preset=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.preset = more
align.preset=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.preset = 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 (for example, Ammonite) REPL.
@ import $ivy.`org.scalameta:scalameta_2.12:4.4.10`, 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.tokens.add
Usage is identical to align.tokens
, but token pairs will be added to
defaults rather than replacing them.
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
Default changed from
true
tofalse
in v1.6.
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
Default changed from
true
tofalse
in v1.6.
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
align.stripMargin
See assumeStandardLibraryStripMargin.
Default: align.stripMargin = true
This functionality is enabled in all presets except align.preset=none
where it
was disabled since the parameter's introduction in v2.5.0.
align.multiline
If this flag is set, when alignment is applied, multiline statements will not be excluded from search of tokens to align.
Since v2.5.0.
Default: align.multiline = false
for {
a <- aaa
bbb <- bb
cccccc <- c {
3
}
dd <- ddddd
} yield ()
for {
a <- aaa
bbb <- bb
cccccc <- c {
3
}
dd <- ddddd
} yield ()
Config for this example:
align.preset = more
align.multiline = true
for {
a <- aaa
bbb <- bb
cccccc <- c {
3
}
dd <- ddddd
} yield ()
for {
a <- aaa
bbb <- bb
cccccc <- c {
3
}
dd <- ddddd
} yield ()
Config for this example:
align.preset = more
align.multiline = 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.source
Since v2.5.0.
This parameter controls the general approach to line breaks, and whether to take into account existing newlines in the source. The default value (if the parameter is not specified) is the classic, original way. Below are the alternatives.
These alternatives are EXPERIMENTAL and might change in the future without regard to any
edition
settings, until fully released (and this message deleted).
newlines.source=keep
This approach attempts to preserve line breaks in the input whenever possible.
newlines.source=fold,unfold
These two approaches completely ignore existing line breaks, except around comments and blank lines (i.e., multiple consecutive newlines).
Might require increasing runner limits (
runner.optimizer.maxVisitsPerToken
, possibly evenrunner.maxStateVisits
), to avoid SearchStateExploded exceptions.
fold
attempts to remove line breaks whenever possible resulting in a more
horizontal, or vertically compact look.
unfold
, on the other hand, is intended for those who prefer a more vertical,
or horizontally compact look.
Both settings attempt to play nice with other parameters, but some combinations are prohibited and will result in an error.
Config-style formatting
This formatting applies to argument lists in class definitions and method calls.
It normally involves a newline after the opening parenthesis (or after the
implicit
keyword) and a newline before the closing parenthesis.
As part of the formatting output, arguments are output one per line (but this is not used in determining whether the source uses config-style formatting).
While this parameter is not technically under the newlines
section, it
logically belongs there.
optIn.configStyleArguments
If true, applies config-style formatting:
- if single-line formatting is impossible
- if the source uses config-style and
newlines.source = classic/keep
- if other parameters force config-style (see below)
Default: optIn.configStyleArguments = true
object a {
// keeps single line
def method1(a: Int, b: String): Boolean
// forces config style
def method2(
a: Int,
b: String,
c: String
): Boolean
// preserves config style
def method3(
a: Int,
b: String,
c: String
): Boolean
}
object a {
// keeps single line
def method1(a: Int, b: String): Boolean
// forces config style
def method2(a: Int, b: String, c: String): Boolean
// preserves config style
def method3(
a: Int, b: String, c: String
): Boolean
}
Config for this example:
optIn.configStyleArguments = true
maxColumn=45
Forcing config style
Controls parameters which trigger forced config-style formatting. All conditions must be satisfied in order for this rule to apply.
# Defaults
runner.optimizer.forceConfigStyleOnOffset = 150
runner.optimizer.forceConfigStyleMinArgCount = 2
runner.optimizer.forceConfigStyleOnOffset
: applies to method calls; if positive, specifies the minimum character distance between the matching parentheses, excluding any whitespacerunner.optimizer.forceConfigStyleMinArgCount
applies to method calls; specifies the minimum number of arguments
object a {
// this is a definition, not a method call
def method(a: String, b: String = null): Boolean
// keeps single line; min offset not satisfied
method(a, b)
// keeps single line; min arg not satisfied
method(SomeVeryVeryVeryVeryLongArgument)
// forces config style
method(
foo,
bar
)
}
object a {
// this is a definition, not a method call
def method(a: String, b: String = null): Boolean
// keeps single line; min offset not satisfied
method(a, b)
// keeps single line; min arg not satisfied
method(SomeVeryVeryVeryVeryLongArgument)
// forces config style
method(foo, bar)
}
Config for this example:
optIn.configStyleArguments = true
runner.optimizer.forceConfigStyleOnOffset = 5
runner.optimizer.forceConfigStyleMinArgCount = 2
maxColumn = 60
danglingParentheses
While this parameter is not technically under the newlines
section, it
logically belongs there.
danglingParentheses.defnSite
Default: danglingParentheses.defnSite = true
object a {
// defnSite
def method(
a: Int,
b: String
): Boolean
// callSite
method(
argument1,
argument2)
}
object a {
// defnSite
def method(a: Int, b: String): Boolean
// callSite
method(argument1, argument2)
}
Config for this example:
danglingParentheses.defnSite = true
danglingParentheses.callSite = false
maxColumn=25
danglingParentheses.callSite
Default: danglingParentheses.callSite = true
object a {
// defnSite
def method(
a: Int,
b: String): Boolean
// callSite
method(
argument1,
argument2
)
}
object a {
// defnSite
def method(a: Int, b: String): Boolean
// callSite
method(argument1, argument2)
}
Config for this example:
danglingParentheses.defnSite = false
danglingParentheses.callSite = true
maxColumn=25
danglingParentheses.ctrlSite
Since v2.5.0.
Forces dangling on open/close parens around control structures (if
, while
,
for
) when line breaks must occur.
Default: danglingParentheses.ctrlSite = true
if (something) {
// nothing
}
if (
something_else
) {
// nothing
}
if (something) {
// nothing
}
if (something_else) {
// nothing
}
Config for this example:
danglingParentheses.ctrlSite = true
maxColumn=20
danglingParentheses.exclude
Since v2.5.0.
When the appropriate danglingParentheses
flag (e.g., defnSite
) has been set,
this parameter can be used to limit contexts where dangling is applied
(currently, class
, trait
, enum
, extension
and def
are supported).
Default: danglingParentheses.exclude = []
def other(a: String, b: String)(
c: String,
d: String) = a + b + c
other(a, b)(c, d)
def other(a: String, b: String)(c: String, d: String) = a + b + c
other(a, b)(c, d)
Config for this example:
continuationIndent.defnSite = 2
danglingParentheses.defnSite = true
danglingParentheses.exclude = [def]
newlines.topLevelStatements
Since v2.5.0.
This parameter, together with its companions below, controls whether to enforce a blank line before and/or after a top-level statement spanning a certain number of lines.
This parameter will not cause any blank lines to be removed.
Default: newlines.topLevelStatements = []
import org.scalafmt
package core { // no newline added here
class C1 {}
object O { // nor here
val x1 = 1
val x2 = 2
def A = "A"
def B = "B"
} // nor here
class C2 {}
}
import org.scalafmt
package core { // no newline added here
class C1 {}
object O { // nor here
val x1 = 1
val x2 = 2
def A = "A"
def B = "B"
} // nor here
class C2 {}
}
Config for this example:
newlines.topLevelStatements = []
import org.scalafmt
package core {
class C1 {}
object O {
val x1 = 1
val x2 = 2
def A = "A"
def B = "B"
}
class C2 {}
}
import org.scalafmt
package core {
class C1 {}
object O {
val x1 = 1
val x2 = 2
def A = "A"
def B = "B"
}
class C2 {}
}
Config for this example:
newlines.topLevelStatements = [before]
import org.scalafmt
package core {
class C1 {}
object O {
val x1 = 1
val x2 = 2
def A = "A"
def B = "B"
}
class C2 {}
}
import org.scalafmt
package core {
class C1 {}
object O {
val x1 = 1
val x2 = 2
def A = "A"
def B = "B"
}
class C2 {}
}
Config for this example:
newlines.topLevelStatements = [after]
import org.scalafmt
package core {
class C1 {}
object O {
val x1 = 1
val x2 = 2
def A = "A"
def B = "B"
}
class C2 {}
}
import org.scalafmt
package core {
class C1 {}
object O {
val x1 = 1
val x2 = 2
def A = "A"
def B = "B"
}
class C2 {}
}
Config for this example:
newlines.topLevelStatements = [before,after]
newlines.topLevelStatementsMinBreaks
Since v2.5.0.
This parameter sets the minimum of line breaks between the first and last line
of a top-level statement (i.e., one less than the number of lines the statement
spans). For instance, newlines.topLevelStatementsMinBreaks=0
will apply to all
top-level statements, whereas 1 will require at least one line break (or a
multi-line statement).
Default: newlines.topLevelStatementsMinBreaks = 1
package core {
object O {
val x1 = 1
val x2 = 2
def A =
"A"
def B = {
"B"
}
}
}
package core {
object O {
val x1 = 1
val x2 = 2
def A =
"A"
def B = {
"B"
}
}
}
Config for this example:
newlines.topLevelStatements = [before,after]
newlines.topLevelStatementsMinBreaks = 0
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.topLevelStatements = [before,after]
newlines.topLevelStatementsMinBreaks = 2
newlines.beforeMultiline
Since 2.7.0
This parameter controls whether to force a new line before a multi-line body of
case/if/val
and how to format it if the space is allowed. (For multi-line
bodies of method definitions, please see
newlines.beforeMultilineDef
below.)
It accepts the same values as newlines.source
(and defaults
to that parameter's setting).
NB: for breaks before parameters of a multi-line lambda, use multiline
with
newlines.beforeCurlyLambdaParams
.
a match {
// had space after "=>"
case a =>
if (step != 0)
d.name should be("dir" + step)
// had newline after "=>"
case a =>
if (step != 0)
d.name should be("dir" + step)
}
a match {
// had space after "=>"
case a => if (step != 0)
d.name should be("dir" + step)
// had newline after "=>"
case a =>
if (step != 0)
d.name should be("dir" + step)
}
Config for this example:
newlines.beforeMultiline = unfold
a match {
// had space after "=>"
case a => if (step != 0)
d.name should be("dir" + step)
// had newline after "=>"
case a => if (step != 0)
d.name should be("dir" + step)
}
a match {
// had space after "=>"
case a => if (step != 0)
d.name should be("dir" + step)
// had newline after "=>"
case a =>
if (step != 0)
d.name should be("dir" + step)
}
Config for this example:
newlines.beforeMultiline = fold
a match {
// had space after "=>"
case a => if (step != 0)
d.name should be("dir" + step)
// had newline after "=>"
case a =>
if (step != 0)
d.name should be("dir" + step)
}
a match {
// had space after "=>"
case a => if (step != 0)
d.name should be("dir" + step)
// had newline after "=>"
case a =>
if (step != 0)
d.name should be("dir" + step)
}
Config for this example:
newlines.beforeMultiline = keep
a match {
// had space after "=>"
case a =>
if (step != 0)
d.name should be("dir" + step)
// had newline after "=>"
case a =>
if (step != 0)
d.name should be("dir" + step)
}
a match {
// had space after "=>"
case a => if (step != 0)
d.name should be("dir" + step)
// had newline after "=>"
case a =>
if (step != 0)
d.name should be("dir" + step)
}
Config for this example:
# newlines.beforeMultiline = classic
newlines.beforeMultilineDef
Since 2.7.0
This parameter applies to multi-line definitions only. It accepts the same
values as newlines.beforeMultiline
(and defaults
to that parameter's setting).
It replaced deprecated boolean newlines.alwaysBeforeMultilineDef
(with false
mapped to fold
and true
to unfold
).
// had space after "="
def foo: String =
"123".map { x =>
x.toUpper
}
// had newline after "="
def foo: String =
"123".map { x =>
x.toUpper
}
// had space after "="
def foo: String = "123".map { x =>
x.toUpper
}
// had newline after "="
def foo: String =
"123".map { x =>
x.toUpper
}
Config for this example:
newlines.beforeMultilineDef = unfold
// had space after "="
def foo: String = "123".map { x =>
x.toUpper
}
// had newline after "="
def foo: String = "123".map { x =>
x.toUpper
}
// had space after "="
def foo: String = "123".map { x =>
x.toUpper
}
// had newline after "="
def foo: String =
"123".map { x =>
x.toUpper
}
Config for this example:
newlines.beforeMultilineDef = fold
// had space after "="
def foo: String = "123".map { x =>
x.toUpper
}
// had newline after "="
def foo: String =
"123".map { x =>
x.toUpper
}
// had space after "="
def foo: String = "123".map { x =>
x.toUpper
}
// had newline after "="
def foo: String =
"123".map { x =>
x.toUpper
}
Config for this example:
newlines.beforeMultilineDef = keep
// had space after "="
def foo: String = "123".map { x =>
x.toUpper
}
// had newline after "="
def foo: String =
"123".map { x =>
x.toUpper
}
// had space after "="
def foo: String = "123".map { x =>
x.toUpper
}
// had newline after "="
def foo: String =
"123".map { x =>
x.toUpper
}
Config for this example:
# newlines.beforeMultilineDef = classic
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
newlines.beforeCurlyLambdaParams
This parameter controls whether a newline is forced between the opening curly
brace and the parameters of a lambda or partial function. Added in 2.7.0,
replacing boolean alwaysBeforeCurlyBraceLambdaParams
.
Default: newlines.beforeCurlyLambdaParams = "never"
// should keep one-line
x.map { x => s"${x._1} -> ${x._2}" }
x.map { case (c, i) => s"$c -> $i" }
// should break on arrow since case doesn't fit on a line
x.zipWithIndex.map { case (c, i) =>
s"$c -> $i"
}
x.zipWithIndex.map { case (c, i) =>
s"$c -> $i (long comment)"
}
// should keep one-line
x.map { x => s"${x._1} -> ${x._2}" }
x.map { case (c, i) => s"$c -> $i" }
// should break on arrow since case doesn't fit on a line
x.zipWithIndex.map { case (c, i) => s"$c -> $i" }
x.zipWithIndex.map { case (c, i) => s"$c -> $i (long comment)" }
Config for this example:
newlines.beforeCurlyLambdaParams = never
// should break on brace, though fits on the same line
x.map {
x => s"${x._1} -> ${x._2}"
}
x.map {
case (c, i) => s"$c -> $i"
}
x.zipWithIndex.map {
case (c, i) =>
s"$c -> $i (long comment)"
}
// should break on brace and arrow as lambda doesn't fit on a line
x.zipWithIndex.map {
x =>
s"${x._1} -> ${x._2} (long comment)"
}
// should break on brace, though fits on the same line
x.map { x => s"${x._1} -> ${x._2}" }
x.map { case (c, i) => s"$c -> $i" }
x.zipWithIndex.map { case (c, i) => s"$c -> $i (long comment)" }
// should break on brace and arrow as lambda doesn't fit on a line
x.zipWithIndex.map { x => s"${x._1} -> ${x._2} (long comment)" }
Config for this example:
newlines.beforeCurlyLambdaParams = always
// should keep one-line
x.map { x => s"${x._1} -> ${x._2}" }
x.map { case (c, i) => s"$c -> $i" }
// should break on brace as lambda doesn't fit on the same line
x.zipWithIndex.map {
x => s"${x._1} -> ${x._2}"
}
x.zipWithIndex.map {
case (c, i) => s"$c -> $i"
}
// should break on brace and arrow as lambda doesn't fit on a line
x.zipWithIndex.map {
x =>
s"${x._1} -> ${x._2} (long comment)"
}
x.zipWithIndex.map {
case (c, i) =>
s"$c -> $i (long comment)"
}
// should keep one-line
x.map { x => s"${x._1} -> ${x._2}" }
x.map { case (c, i) => s"$c -> $i" }
// should break on brace as lambda doesn't fit on the same line
x.zipWithIndex.map { x => s"${x._1} -> ${x._2}" }
x.zipWithIndex.map { case (c, i) => s"$c -> $i" }
// should break on brace and arrow as lambda doesn't fit on a line
x.zipWithIndex.map { x => s"${x._1} -> ${x._2} (long comment)" }
x.zipWithIndex.map { case (c, i) => s"$c -> $i (long comment)" }
Config for this example:
newlines.beforeCurlyLambdaParams = multiline
// should keep one-line
x.map { x => s"${x._1} -> ${x._2}" }
x.map { case (c, i) => s"$c -> $i" }
// should break after arrow as lambda doesn't fit on the same line
x.zipWithIndex.map { x =>
s"${x._1} -> ${x._2}"
}
x.zipWithIndex.map { x =>
s"${x._1} -> ${x._2} (long comment)"
}
// should break on brace as lambda doesn't fit on the same line
x.zipWithIndex.map {
case (c, i) => s"$c -> $i"
}
// should break on brace and arrow as lambda doesn't fit on a line
x.zipWithIndex.map {
case (c, i) =>
s"$c -> $i (long comment)"
}
// should keep one-line
x.map { x => s"${x._1} -> ${x._2}" }
x.map { case (c, i) => s"$c -> $i" }
// should break after arrow as lambda doesn't fit on the same line
x.zipWithIndex.map { x => s"${x._1} -> ${x._2}" }
x.zipWithIndex.map { x => s"${x._1} -> ${x._2} (long comment)" }
// should break on brace as lambda doesn't fit on the same line
x.zipWithIndex.map { case (c, i) => s"$c -> $i" }
// should break on brace and arrow as lambda doesn't fit on a line
x.zipWithIndex.map { case (c, i) => s"$c -> $i (long comment)" }
Config for this example:
newlines.beforeCurlyLambdaParams = multilineWithCaseOnly
newlines.afterCurlyLambdaParams
This parameter controls handling of newlines after the arrow following the parameters of a curly brace lambda or partial function, and whether a space can be used for one-line formatting of the entire function body (if allowed but the body doesn't fit, a break is always forced).
This parameter was renamed in 2.7.0 from afterCurlyLambda
, for clarity and
consistency with beforeCurlyLambdaParams
defined above.
Default: newlines.afterCurlyLambdaParams = "never"
// remove all blank lines if any
// one-line formatting is allowed
something.map { x => f(x) }
something.map { x => f(x) }
// remove all blank lines if any
// one-line formatting is allowed
something.map { x =>
f(x)
}
something.map { x => f(x) }
Config for this example:
newlines.afterCurlyLambdaParams = squash
// remove all blank lines if any
// one-line formatting depends on newlines.source:
// yes for fold; no for unfold; otherwise, only if there was no break
something.map { x =>
f(x)
}
something.map { x => f(x) }
// remove all blank lines if any
// one-line formatting depends on newlines.source:
// yes for fold; no for unfold; otherwise, only if there was no break
something.map { x =>
f(x)
}
something.map { x => f(x) }
Config for this example:
newlines.afterCurlyLambdaParams = never
// if blank lines are present, keep only one
// one-line formatting depends on newlines.source:
// yes for fold; no for unfold; otherwise, only if there was no break
something.map { x =>
f(x)
}
something.map { x => f(x) }
// if blank lines are present, keep only one
// one-line formatting depends on newlines.source:
// yes for fold; no for unfold; otherwise, only if there was no break
something.map { x =>
f(x)
}
something.map { x => f(x) }
Config for this example:
newlines.afterCurlyLambdaParams = preserve
// ensure a single blank line
// one-line formatting is not allowed
something.map { x =>
f(x)
}
something.map { x =>
f(x)
}
// ensure a single blank line
// one-line formatting is not allowed
something.map { x =>
f(x)
}
something.map { x => f(x) }
Config for this example:
newlines.afterCurlyLambdaParams = always
implicit
parameter list modifier
Newlines around Since v2.5.0.
using
parameter and argument list modifier
Newlines around Since v3.0.0
using
soft keyword was introduced in Scala 3 and is supported in scalafmt.
The settings newlines.implicitParamListModifierPrefer
and
newlines.implicitParamListModifierForce
are from now on aliases for
newlines.usingParamListModifierPrefer
and newlines.usingParamListModifierForce
.
By picking one of them formatting will be applied at the same time to both implicit
and using
.
Besides parameter lists, using
can also be used with argument lists hence
provided rules will then also be applied to the argument lists.
Prefer After (default)
Prefers newline after
implicit
. Newline will be added unless the entire implicit parameter list fits on a line, or config style is false. Newline can also be added before if the keyword itself would overflow the line.
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
newlines.implicitParamListModifierPrefer = after
Prefer Before
Prefers newline before
implicit
. Newline will not be added if the entire implicit parameter list fits on a line.
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
newlines.implicitParamListModifierPrefer = before
Force Before
If set, forces newline before
implicit
. Otherwise, newline can still be added if the keyword would overflow the line.
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
newlines.implicitParamListModifierForce = [before]
Force After
If set, forces newline after
implicit
. Otherwise, newline can still be added unlessbefore
is true, or the entire implicit parameter list fits on a line, or config style is 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
newlines.implicitParamListModifierForce = [after]
Force both before and after
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
newlines.implicitParamListModifierForce = [before,after]
optIn.configStyleArguments
Implicit with While config-style normally requires a newline after the opening parenthesis,
postponing that break until after the implicit
keyword is allowed if other
parameters require keeping this keyword attached to the opening brace.
Therefore, any of the parameters described in this section will take precedence
even when optIn.configStyleArguments = true
is used.
newlines.afterInfix
Since v2.5.0.
This parameter (and its companions) controls formatting around infix expressions.
The default value depends on
newlines.source
(see below).
newlines.afterInfix=keep
This approach preserves line breaks in the input. This is the original
behaviour, and default for newlines.source=classic,keep
.
newlines.afterInfix=many,some
These approaches completely ignore existing newlines around infix, always use
a space before an infix operator and occasionally break after it. some
is
default for newlines.source=fold
, and many
for newlines.source=unfold
.
Might require increasing runner limits (
runner.optimizer.maxVisitsPerToken
, possibly evenrunner.maxStateVisits
), to avoid SearchStateExploded exceptions.
some
will introduce fewer line breaks than many
. Both will attempt to break
after
higher-precedence operators,
and both will always break before an expression enclosed in matching
parentheses.
newlines.afterInfixMaxCountPerFile
Default: newlines.afterInfixMaxCountPerFile = 500
If the total number of infix operations in the entire file exceeds
newlines.afterInfixMaxCountPerFile
, the formatter automatically switches to
newlines.afterInfix=keep
for this file.
newlines.afterInfixMaxCountPerExprForSome
Default: newlines.afterInfixMaxCountPerExprForSome = 10
If newlines.afterInfix
is set to some
and the number of infix operations in
a given expression sequence (top-level or enclosed in parens/braces) exceeds
newlines.afterInfixMaxCountPerExprForSome
, the formatter switches to many
for that sequence only.
newlines.afterInfixBreakOnNested
Default: newlines.afterInfixBreakOnNested = false
If enabled, will force line breaks around a nested parenthesized sub-expression in a multi-line infix expression.
newlines.avoidForSimpleOverflow
A list parameter (of comma-separated flags), with possible flags described
below. These flags relax formatting rules to allow occasional line overflow
(i.e., when line exceeds maxColumn
) in simple cases instead of introducing a
newline.
Default: newlines.avoidForSimpleOverflow = []
newlines.avoidForSimpleOverflow=[tooLong]
Since v2.6.0.
This flag tries to avoid introducing a newline if the line would overflow even with a newline.
object Example {
foo_bar_baz("the quick brown fox jumps over the lazy dog") {
println("")
}
foo_bar_baz(
"the quick brown fox jumps over a dog") {
println("")
}
}
object Example {
foo_bar_baz("the quick brown fox jumps over the lazy dog") {
println("")
}
foo_bar_baz("the quick brown fox jumps over a dog") {
println("")
}
}
Config for this example:
maxColumn = 50
danglingParentheses.callSite = false
newlines.avoidForSimpleOverflow = [tooLong]
newlines.avoidForSimpleOverflow=[punct]
Since v2.6.0.
This flag tries to avoid a newline if the line would overflow only because of trailing punctuation (non-alphanum symbols of length 1).
With the flag set:
class Engine[TD, EI, PD, Q, P, A](
val dataSourceClassMap: Map[String, Class[_ <: BaseDataSource[TD, EI, Q, A]]]
) {}
class Engine[TD, EI, PD, Q, P, A](
val dataSourceClassMap: Map[
String,
Class[_ <: BaseDataSource[TD, EI, Q, A]]]) {}
Config for this example:
maxColumn = 80
newlines.avoidForSimpleOverflow = [punct]
newlines.avoidInResultType
If true, newlines in definition result type will only be used if formatting
without them is impossible. This parameter was added in 2.7.0, replacing
neverInResultType
.
Default: newlines.avoidInResultType = false
// no newlines in result type
def permissionState(
a: A = js.native
): js.Promise[PushPermissionState] = js.native
// no newlines in result type
val permissionState
: js.Promise[PushPermissionState] = js.native
// can't format without newlines
implicit protected val td: TildeArrow {
type Out = RouteTestResult
} = TildeArrow.injectIntoRoute
// no newlines in result type
def permissionState(a: A = js.native): js.Promise[PushPermissionState] = js.native
// no newlines in result type
val permissionState: js.Promise[PushPermissionState] = js.native
// can't format without newlines
implicit protected val td: TildeArrow {
type Out = RouteTestResult } = TildeArrow.injectIntoRoute
Config for this example:
maxColumn = 40
newlines.avoidInResultType = true
newlines.neverBeforeJsNative = true
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
List(1, 2, 3).map(x => x + 1)
List(1, 2, 3).map { x => x + 1 }
Config for this example:
rewrite.rules = [RedundantBraces]
Entire power of RedundantBraces
can be accessed with
newlines.afterCurlyLambdaParams=squash
. It will try to squash lambda body in
one line and then replace braces with parens:
List(1, 2, 3).map(x => x + 1)
List(1, 2, 3).map { x =>
println("you can't squash me!")
x + 1
}
List(1, 2, 3).map { x =>
x + 1
}
List(1, 2, 3).map { x =>
println("you can't squash me!")
x + 1
}
Config for this example:
rewrite.rules = [RedundantBraces]
newlines.afterCurlyLambdaParams=squash
Configuration options
Default: rewrite.redundantBraces.generalExpressions = true
while (x < 10)
x += 1
str match {
case "a" =>
println("ok")
case _ =>
println("not ok")
}
while (x < 10) {
x += 1
}
str match {
case "a" => {
println("ok")
}
case _ => {
println("not ok")
}
}
Config for this example:
rewrite.rules = [RedundantBraces]
rewrite.redundantBraces.generalExpressions = true
Default: rewrite.redundantBraces.ifElseExpressions = false
if (a > b)
doSomething()
else
doAnything()
if (a > b) {
doSomething()
} else {
doAnything()
}
Config for this example:
rewrite.rules = [RedundantBraces]
rewrite.redundantBraces.ifElseExpressions = true
Default: rewrite.redundantBraces.methodBodies = true
def f() =
1 + 1
def f() = {
1 + 1
}
Config for this example:
rewrite.rules = [RedundantBraces]
rewrite.redundantBraces.methodBodies = true
Default: rewrite.redundantBraces.includeUnitMethods = true
Affects only functions with explicitly specified Unit
type
def f() =
1 + 1
def x(): Unit = {
println("example")
}
def f() = {
1 + 1
}
def x(): Unit = {
println("example")
}
Config for this example:
rewrite.rules = [RedundantBraces]
rewrite.redundantBraces.methodBodies = true
rewrite.redundantBraces.includeUnitMethods = false
Default: rewrite.redundantBraces.stringInterpolation = false
s"user id is $id"
s"user id is ${id}"
Config for this example:
rewrite.rules = [RedundantBraces]
rewrite.redundantBraces.stringInterpolation = true
rewrite.redundantBraces.parensForOneLineApply
is true
by default for
edition
>= 2020-01. See also
newlines.afterCurlyLambdaParams = squash.
xs.map(x => x + 1)
xs.map { x => x + 1 }
Config for this example:
rewrite.rules = [RedundantBraces]
rewrite.redundantBraces.parensForOneLineApply = true
Default: rewrite.redundantBraces.maxLines = 100
def f() =
collection
.map(x => x + 1)
.filter(_ < 10)
.map(_ * 2)
def f() = {
collection
.map(x => x + 1)
.filter(_ < 10)
.map(_ * 2)
.headOption
}
def f() = {
collection
.map(x => x + 1)
.filter(_ < 10)
.map(_ * 2)
}
def f() = {
collection
.map(x => x + 1)
.filter(_ < 10)
.map(_ * 2)
.headOption
}
Config for this example:
rewrite.rules = [RedundantBraces]
rewrite.redundantBraces.maxLines = 3
RedundantParens
for {
a <- b
if a.nonEmpty
} yield a
val z = insertData *> readDatabase(id)
for {
a <- b
if (a.nonEmpty)
} yield a
val z = (insertData *> readDatabase(id))
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]
Trailing commas
See SIP
The rule handles how trailing commas are treated in case of a dangling closing delimiter (parenthesis or bracket for definitions or invocations, brace for import statements only).
Regardless of the setting, trailing commas are always removed if the closing delimiter is not dangling (i.e., follows the final argument without a line break).
This logic is not triggered via the
rewrite.rules
parameter, but by settingtrailingCommas
.
Default: trailingCommas = "never"
never
Trailing commas: Makes sure there are no trailing commas:
import a.{b, c}
def method1(
a: Int,
b: Long
) = {}
def method2(
a: Int,
b: Long*
) = {}
def method3(
a: Int
) = {}
method1(
a,
b
)
method2(
a,
b: _*
)
method3(
a
)
import a.{
b,
c,
}
def method1(
a: Int,
b: Long,
) = {}
def method2(
a: Int,
b: Long*,
) = {}
def method3(
a: Int,
) = {}
method1(
a,
b,
)
method2(
a,
b: _*,
)
method3(
a,
)
Config for this example:
trailingCommas = never
preserve
Trailing commas: Keeps any trailing commas:
import a.{b, c}
def method1(
a: Int,
b: Long,
) = {}
def method2(
a: Int,
b: Long*
) = {}
def method3(
a: Int,
) = {}
method1(
a,
b
)
method2(
a,
b: _*,
)
method3(
a,
)
import a.{
b,
c,
}
def method1(
a: Int,
b: Long,
) = {}
def method2(
a: Int,
b: Long*
) = {}
def method3(
a: Int,
) = {}
method1(
a,
b
)
method2(
a,
b: _*,
)
method3(
a,
)
Config for this example:
trailingCommas = preserve
always
Trailing commas: Makes sure there are trailing commas:
import a.{b, c}
def method1(
a: Int,
b: Long,
) = {}
def method2(
a: Int,
b: Long*,
) = {}
def method3(
a: Int,
) = {}
method1(
a,
b,
)
method2(
a,
b: _*,
)
method3(
a,
)
import a.{
b,
c
}
def method1(
a: Int,
b: Long
) = {}
def method2(
a: Int,
b: Long*
) = {}
def method3(
a: Int
) = {}
method1(
a,
b
)
method2(
a,
b: _*
)
method3(
a
)
Config for this example:
trailingCommas = always
multiple
Trailing commas: Since v2.5.0.
Makes sure there are trailing commas for multiple-argument expressions only, except when the last argument is repeated:
import a.{b, c}
def method1(
a: Int,
b: Long,
) = {}
def method2(
a: Int,
b: Long*
) = {}
def method3(
a: Int
) = {}
method1(
a,
b,
)
method2(
a,
b: _*
)
method3(
a
)
import a.{
b,
c
}
def method1(
a: Int,
b: Long
) = {}
def method2(
a: Int,
b: Long*,
) = {}
def method3(
a: Int,
) = {}
method1(
a,
b
)
method2(
a,
b: _*,
)
method3(
a,
)
Config for this example:
trailingCommas = multiple
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 the 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.excludeDanglingParens
This parameter has been deprecated, please use danglingParentheses.exclude. Keep in mind, though, that the new parameter is empty by default while the old one isn't, so to use empty exclude list, one must set the old
verticalMultiline.excludeDanglingParens=[]
.
Default: verticalMultiline.excludeDanglingParens = ["
class", "
trait"]
def other(
a: String,
b: String
)(
c: String,
d: String) = a + b + c
other(a, b)(c, d)
def other(a: String, b: String)(c: String, d: String) = a + b + c
other(a, b)(c, d)
Config for this example:
continuationIndent.defnSite = 2
verticalMultiline.excludeDanglingParens = [def]
verticalMultiline.atDefnSite = true
verticalMultiline.arityThreshold = 2
verticalMultiline.newlineAfterOpenParen = true
implicit
parameter lists
Vertical multiline with Also see the general section on implicit parameter lists.
Before only
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
newlines.implicitParamListModifierForce = [before]
After only
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
newlines.implicitParamListModifierForce = [after]
Before and after
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
newlines.implicitParamListModifierForce = [before,after]
Comment processing
comments
comments.wrap
Since v2.6.0.
Allows wrapping comments exceeding maxColumn
.
Default: comments.wrap = "no"
comments.wrap = standalone
A standalone comment is one which is surrounded by line breaks.
/* long multiline
* comment */
/* long singleline
* comment */
val a = 1 // short
val b =
2 // long singleline comment
/* long multiline comment */
// long singleline comment
val a = 1 // short
val b = 2 // long singleline comment
Config for this example:
maxColumn = 20
comments.wrap = standalone
comments.wrap = trailing
A trailing comment is one which is followed by a line break.
/* long multiline
* comment */
/* long singleline
* comment */
val a = 1 // short
val b =
2 /* long
* singleline
* comment */
/* long multiline comment */
// long singleline comment
val a = 1 // short
val b = 2 // long singleline comment
Config for this example:
maxColumn = 20
comments.wrap = trailing
comments.wrapStandaloneSlcAsSlc
Since v2.6.0.
This parameter allows formatting a standalone single-line comment (i.e., //
)
to be wrapped using the same type, not a multi-line comment (/* ... */
).
Default: comments.wrapStandaloneSlcAsSlc = false
// long singleline
// comment
val b =
2 /* long
* singleline
* comment */
// long singleline comment
val b = 2 // long singleline comment
Config for this example:
maxColumn = 20
comments.wrap = trailing
comments.wrapStandaloneSlcAsSlc = true
docstrings
docstrings.style
Since v2.6.0.
Default: docstrings.style = "SpaceAsterisk"
docstrings.style = Preserve
Prohibits formatting of docstrings. All other docstrings
parameters are
ignored.
/** do not touch
* this style
* keep the text as-is
*/
/** do not touch
* this style
* keep the text as-is
*/
Config for this example:
docstrings.style = Preserve
docstrings.style = Asterisk
This variant used to be called JavaDoc
.
/**
* Skip first line, format intermediate lines with an asterisk
* below the first asterisk of the first line (aka JavaDoc)
*/
/** Skip first line, format intermediate lines with an asterisk
* below the first asterisk of the first line (aka JavaDoc)
*/
Config for this example:
docstrings.style = Asterisk
docstrings.style = SpaceAsterisk
This variant used to be called ScalaDoc
.
/** Format intermediate lines with a space and an asterisk,
* both below the two asterisks of the first line
*/
/** Format intermediate lines with a space and an asterisk,
* both below the two asterisks of the first line
*/
Config for this example:
docstrings.style = SpaceAsterisk
docstrings.style = AsteriskSpace
/** Format intermediate lines with an asterisk and a space,
* both below the two asterisks of the first line
*/
/** Format intermediate lines with an asterisk and a space,
* both below the two asterisks of the first line
*/
Config for this example:
docstrings.style = AsteriskSpace
docstrings.oneline
Since v2.6.0. Ignored for
docstrings.style = Preserve
.
Default: docstrings.oneline = "keep"
docstrings.oneline = fold
/** Scaladoc oneline */
/** Scaladoc multiline */
val a = 1
/** Scaladoc oneline */
/**
* Scaladoc multiline
*/
val a = 1
Config for this example:
docstrings.style = Asterisk
docstrings.oneline = fold
docstrings.oneline = unfold
/**
* Scaladoc oneline
*/
/**
* Scaladoc multiline
*/
val a = 1
/** Scaladoc oneline */
/**
* Scaladoc multiline
*/
val a = 1
Config for this example:
docstrings.style = Asterisk
docstrings.oneline = unfold
docstrings.oneline = keep
/** Scaladoc oneline */
/**
* Scaladoc multiline
*/
val a = 1
/** Scaladoc oneline */
/**
* Scaladoc multiline
*/
val a = 1
Config for this example:
docstrings.style = Asterisk
docstrings.oneline = keep
docstrings.wrap
Will parse scaladoc comments and reformat them.
This functionality is generally limited to standard scaladoc elements and might lead to undesirable results in corner cases; for instance, the scaladoc parser doesn't have proper support of embedded HTML.
However, tables are supported.
Since v2.6.0. Ignored for
docstrings.style = Preserve
.
Default: docstrings.wrap = "no"
/** @param d
* the Double to square,
* meaning multiply by
* itself
* @return
* the result of squaring d
*
* Thus
* - if [[d]] represents a
* negative value:
* a. the result will be
* positive
* a. the value will be
* {{{d * d}}}
* a. it will be the same
* as for `-d`
* - however, if [[d]] is
* positive
* - the value will still
* be {{{d * d}}}
* - i.e., the same as
* {{{(-d) * (-d)}}}
*
* In other words:
* {{{
* res = d * d
* = (-d) * (-d)
* }}}
*/
def pow2(d: Double): Double
/**
* @param d the Double to square, meaning multiply by itself
* @return the result of squaring d
*
* Thus
* - if [[d]] represents a negative value:
* a. the result will be positive
* a. the value will be {{{d * d}}}
* a. it will be the same as for `-d`
* - however, if [[d]] is positive
* - the value will still be {{{d * d}}}
* - i.e., the same as {{{(-d) * (-d)}}}
*
* In other words:
* {{{
* res = d * d
* = (-d) * (-d) }}}
*/
def pow2(d: Double): Double
Config for this example:
docstrings.wrap = yes
maxColumn = 30
docstrings.blankFirstLine
Controls whether to force the first line to be blank in a multiline docstring.
Keep in mind that some combinations of parameters are prohibited (e.g.,
blankFirstLine=keep
contradicts with style=Asterisk
).
Since v2.7.5. Ignored for
docstrings.style = Preserve
ordocstrings.wrap = no
.
Default: docstrings.blankFirstLine = "no"
/** Scaladoc oneline */
/** Scaladoc multiline1
*/
/** Scaladoc multiline2
*/
val a = 1
/** Scaladoc oneline */
/** Scaladoc multiline1
*/
/**
* Scaladoc multiline2
*/
val a = 1
Config for this example:
# do not force a blank first line
docstrings.blankFirstLine = no
docstrings.style = SpaceAsterisk
maxColumn = 30
/** Scaladoc oneline */
/**
* Scaladoc multiline1
*/
/**
* Scaladoc multiline2
*/
val a = 1
/** Scaladoc oneline */
/** Scaladoc multiline1
*/
/**
* Scaladoc multiline2
*/
val a = 1
Config for this example:
# force a blank first line
docstrings.blankFirstLine = yes
docstrings.style = SpaceAsterisk
maxColumn = 30
/** Scaladoc oneline */
/** Scaladoc multiline1
*/
/**
* Scaladoc multiline2
*/
val a = 1
/** Scaladoc oneline */
/** Scaladoc multiline1
*/
/**
* Scaladoc multiline2
*/
val a = 1
Config for this example:
# preserve a blank first line
docstrings.blankFirstLine = keep
docstrings.style = SpaceAsterisk
maxColumn = 30
Disabling or customizing formatting
For code block
There is a possibility to override scalafmt config for a specific code with
// scalafmt: {}
comment:
// scalafmt: { align.preset = most, danglingParentheses.preset = false }
libraryDependencies ++= Seq(
"org.scalameta" %% "scalameta" % scalametaV,
"org.scalacheck" %% "scalacheck" % scalacheckV)
// scalafmt: { align.preset = some, danglingParentheses.preset = true } (back to defaults)
libraryDependencies ++= Seq(
"org.scalameta" %% "scalameta" % scalametaV,
"org.scalacheck" %% "scalacheck" % scalacheckV
)
// scalafmt: { align.preset = most, danglingParentheses.preset = false }
libraryDependencies ++= Seq(
"org.scalameta" %% "scalameta" % scalametaV,
"org.scalacheck" %% "scalacheck" % scalacheckV)
// scalafmt: { align.preset = some, danglingParentheses.preset = true } (back to defaults)
libraryDependencies ++= Seq(
"org.scalameta" %% "scalameta" % scalametaV,
"org.scalacheck" %% "scalacheck" % scalacheckV)
// 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
]
fileOverride
Since v2.5.0.
Allows specifying an additional subset of parameters for each file matching a PathMatcher pattern. For instance,
align.preset = none
fileOverride {
"glob:**/*.sbt" {
align.preset = most
}
"glob:**/src/test/scala/**/*.scala" {
maxColumn = 120
binPack.unsafeCallSite = true
}
}
uses align.preset=none
for all files except .sbt
for which
align.preset=most
will apply. It will also use different parameters for test
suites.
This parameter does not modify which files are formatted.
Spaces
spaces.beforeContextBoundColon
Default: spaces.beforeContextBoundColon = "Never"
def method[A: Bound]: B
def method[A: Bound]: B
def method[A: Bound: Bound2]: B
def method[A: Bound]: B
def method[A : Bound]: B
def method[A: Bound: Bound2]: B
Config for this example:
spaces.beforeContextBoundColon=Never
def method[A : Bound]: B
def method[A : Bound]: B
def method[A : Bound : Bound2]: B
def method[A: Bound]: B
def method[A : Bound]: B
def method[A: Bound: Bound2]: B
Config for this example:
spaces.beforeContextBoundColon=Always
def method[A: Bound]: B
def method[A: Bound]: B
def method[A : Bound : Bound2]: B
def method[A: Bound]: B
def method[A : Bound]: B
def method[A: Bound: Bound2]: B
Config for this example:
spaces.beforeContextBoundColon=IfMultipleBounds
spaces.inImportCurlyBraces
Default: spaces.inImportCurlyBraces = false
import a.b.{ c, d }
import a.b.{c, d}
Config for this example:
spaces.inImportCurlyBraces=true
spaces.inInterpolatedStringCurlyBraces
Since v3.0.0.
Default: spaces.inInterpolatedStringCurlyBraces = false
s"Hello ${ the } world!"
s"Hello ${ th.e } world!"
s"Hello ${ the() } world!"
s"Hello ${the} world!"
s"Hello ${ th.e} world!"
s"Hello ${the() } world!"
Config for this example:
spaces.inInterpolatedStringCurlyBraces = true
s"Hello ${oneHundred}% world!"
s"Hello ${th.e} world!"
s"Hello ${the()} world!"
s"Hello ${ oneHundred }% world!"
s"Hello ${ th.e} world!"
s"Hello ${the() } world!"
Config for this example:
spaces.inInterpolatedStringCurlyBraces = false
spaces.inParentheses
Default: spaces.inParentheses = false
foo( a, b )
foo(a, b)
Config for this example:
spaces.inParentheses=true
spaces.neverAroundInfixTypes
Default: spaces.neverAroundInfixTypes = []
def f: Foo##Repr
def g: Foo \/ Repr
// usage same operator not as type
def e = a ## b
def f: Foo##Repr
def g: Foo\/Repr
// usage same operator not as type
def e = a##b
Config for this example:
spaces.neverAroundInfixTypes=["##"]
spaces.afterKeywordBeforeParen
Default: spaces.afterKeywordBeforeParen = true
if(a) println("HELLO!")
while(a) println("HELLO!")
if (a) println("HELLO!")
while (a) println("HELLO!")
Config for this example:
spaces.afterKeywordBeforeParen = false
spaces.inByNameTypes
Default: spaces.inByNameTypes = true
def foo(a: =>A): A
def foo(a: => A): A
Config for this example:
spaces.inByNameTypes = false
spaces.afterSymbolicDefs
Default: spaces.afterSymbolicDefs = false
def +++ (a: A): F[A]
def +++(a: A): F[A]
Config for this example:
spaces.afterSymbolicDefs=true
Literals
Since v2.5.0.
Scalafmt allows flexible configuration of Integer and Floating Point literals formatting.
Default formatting:
123L
0xfff
0x1abL
10e-1
10e-1d
123l
0XFff
0x1Abl
10E-1
10e-1D
Each literals.*
setting has three available options: Upper
, Lower
,
Unchanged
.
literals.long
Default: literals.long = "Upper"
Responsible for the case of Long
literals suffix L
123L
123l
Config for this example:
literals.long=Upper
literals.float
Default: literals.float = "Lower"
Responsible for the case of Float
literals suffix F
42.0f
42.0F
Config for this example:
literals.float=Lower
literals.double
Default: literals.double = "Lower"
Responsible for the case of Double
literals suffix D
42.0d
42.0d
Config for this example:
literals.double=Lower
literals.hexPrefix
Default: literals.hexPrefix = "Lower"
Responsible for the case of hex integer literals prefix 0x
0x123
0X123
Config for this example:
literals.hexPrefix=Lower
literals.hexDigits
Default: literals.hexDigits = "Lower"
Responsible for the case of hex integer literals digits
0xaaaa
0xaaaaL
0xaAaA
0xaAaAl
Config for this example:
literals.hexDigits=Lower
literals.long=Upper
literals.scientific
Default: literals.scientific = "Lower"
Responsible for the case of Double
literals exponent part
10E-1
10E-1f
10e-1
10e-1f
Config for this example:
literals.scientific=Upper
literals.float=Lower
XML
Controls formatting of Scala embedded within XML.
xmlLiterals.assumeFormatted
Since v2.6.0.
If set, formats embedded Scala relative to containing XML, making the assumption that XML itself is properly formatted. Otherwise, formatting is relative to the outer Scala code which contains the XML literals.
Default: xmlLiterals.assumeFormatted = false
object Example2 {
def apply() = {
<foo>
<bar>{
(1 + 2 + 3).toString(
"some long format"
)
}</bar>
</foo>
}
}
object Example2 {
def apply() = {
<foo>
<bar>{ (1 + 2 + 3).toString("some long format") }</bar>
</foo>
}
}
Config for this example:
maxColumn = 40
xmlLiterals.assumeFormatted = true
object Example2 {
def apply() = {
<foo>
<bar>{
(1 + 2 + 3).toString(
"some long format"
)
}</bar>
</foo>
}
}
object Example2 {
def apply() = {
<foo>
<bar>{ (1 + 2 + 3).toString("some long format") }</bar>
</foo>
}
}
Config for this example:
maxColumn = 40
xmlLiterals.assumeFormatted = false
Binpacking
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
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
binPack.literalsSingleLine = true
See also:
binPack.literalsIncludeSimpleExpr
(to allow a few select methods followed by a few nested single-argument apply calls, with literals as arguments); added in v2.5.0- all other
binPack.literalXXX
parameters (see list at the bottom) are self-explanatory.
binPack.parentConstructors
Parent constructors are C
and D
in class A extends B with C and D
. Changed
from a boolean to a wider set of options in v2.6.0.
Default: binPack.parentConstructors = "never"
Keep in mind that explicitly specifying the default value might change behaviour; other parameters, such as
newlines.source
, could interpret implied default differently but yield to an explicit value.
object A {
trait Foo
extends Bar with Baz
}
object A {
trait Foo
extends Bar
with Baz
}
Config for this example:
binPack.parentConstructors = Always
maxColumn = 30
object A {
trait Foo
extends Bar
with Baz
}
object A {
trait Foo extends Bar with Baz
}
Config for this example:
binPack.parentConstructors = Never
maxColumn = 30
object A {
class Foo(a: Int)
extends Bar with Baz
class Foo(
a: Int
) extends Bar with Baz
}
object A {
class Foo(a: Int)
extends Bar
with Baz
class Foo(
a: Int
)
extends Bar
with Baz
}
Config for this example:
binPack.parentConstructors = Oneline
maxColumn = 30
object A {
class Foo(a: Int, b: Int)
extends Bar with Baz
class Foo(
a: Int,
b: Int
) extends Bar
with Baz
}
object A {
class Foo(a: Int, b: Int)
extends Bar
with Baz
class Foo(
a: Int,
b: Int
) extends Bar with Baz
}
Config for this example:
binPack.parentConstructors = OnelineIfPrimaryOneline
maxColumn = 30
Classic select chains
The parameters below control formatting of select chains when
newlines.source = classic
, and specifically which select expressions are
included in a chain.
Generally, a chain can either be formatted on one line up to the last select, or will have a break on the first select.
includeCurlyBraceInSelectChains
Controls if select followed by curly braces can start a chain.
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
includeNoParensInSelectChains
Controls if select not followed by an apply can start a chain.
Default: includeNoParensInSelectChains = false
List(1)
.toIterator
.buffered
.map(_ + 2)
.filter(_ > 2)
List(1).toIterator.buffered
.map(_ + 2)
.filter(_ > 2)
Config for this example:
includeNoParensInSelectChains = true
List(1).toIterator.buffered
.map(_ + 2)
.filter(_ > 2)
List(1).toIterator.buffered.map(_ + 2).filter(_ > 2)
Config for this example:
includeNoParensInSelectChains = false
optIn.breakChainOnFirstMethodDot
Keeps the break on the first select of the chain if the source contained one. Has no effect if there was no newline in the source.
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
// preserve break on first dot and break on subsequent dots
foo
.map(_ + 1)
.filter(_ > 2)
// preserve break on first dot and break on subsequent dots
foo
.map(_ + 1).filter(_ > 2)
Config for this example:
optIn.breakChainOnFirstMethodDot = true
optIn.breaksInsideChains
Controls whether to preserve a newline before each subsequent select when the very first one used a line break; that is, this parameter doesn't prohibit single-line formatting even if there are source breaks down the chain.
If false, each subsequent select within the chain will behave exactly like the first, that is, either the entire chain will be formatted on one line, or will contain a break on every select.
If true, preserves existence or lack of breaks on subsequent selects if the first select was formatted with a newline.
Default: optIn.breaksInsideChains = false
foo
.bar(_ + 1)
.baz(_ > 2).qux
foo.bar(_ + 1).baz(_ > 2).qux
foo
.bar(_ + 1).baz(_ > 2).qux(
_ * 12
)
foo.bar(_ + 1).baz(_ > 2).qux {
_ * 12
}
foo
.bar(_ + 1)
.baz(_ > 2).qux(_ * 12)
foo.bar(_ + 1)
.baz(_ > 2).qux
foo.bar(_ + 1).baz(_ > 2).qux
foo.bar(_ + 1).baz(_ > 2).qux(_ * 12)
foo.bar(_ + 1).baz(_ > 2).qux { _ * 12 }
foo.bar(_ + 1)
.baz(_ > 2).qux(_ * 12)
Config for this example:
optIn.breaksInsideChains = true
maxColumn = 35
foo
.bar(_ + 1)
.baz(_ > 2)
.qux
foo.bar(_ + 1).baz(_ > 2).qux
foo
.bar(_ + 1)
.baz(_ > 2)
.qux(_ * 12)
foo.bar(_ + 1).baz(_ > 2).qux {
_ * 12
}
foo
.bar(_ + 1)
.baz(_ > 2)
.qux(_ * 12)
foo.bar(_ + 1)
.baz(_ > 2).qux
foo.bar(_ + 1).baz(_ > 2).qux
foo.bar(_ + 1).baz(_ > 2).qux(_ * 12)
foo.bar(_ + 1).baz(_ > 2).qux { _ * 12 }
foo.bar(_ + 1)
.baz(_ > 2).qux(_ * 12)
Config for this example:
optIn.breaksInsideChains = false
maxColumn = 35
optIn.encloseClassicChains
Controls what happens if a chain enclosed in parentheses is followed by additional selects. Those additional selects will be considered part of the enclosed chain if and only if this flag is false.
Since 2.6.2.
Default: optIn.encloseClassicChains = false
(foo.map(_ + 1).map(_ + 1))
.filter(_ > 2)
(foo.map(_ + 1).map(_ + 1))
.filter(_ > 2)
Config for this example:
optIn.encloseClassicChains = true
maxColumn = 30
(foo
.map(_ + 1)
.map(_ + 1))
.filter(_ > 2)
(foo.map(_ + 1).map(_ + 1))
.filter(_ > 2)
Config for this example:
optIn.encloseClassicChains = false
maxColumn = 30
Scala 3
Scalafmt has basic support for Scala 3 features that can be enabled by changing the dialect of the Scalafmt parser.
runner.dialect = Scala3
---
open class MyOpenClass()
val myQuote = '{ expr }
val mySplice = ${ expr }
enum class Weekday {
case Monday, Tuesday, Wednesday, Thursday, Friday
}
Miscellaneous
optIn.forceBlankLineBeforeDocstring
If true, always insert a blank line before docstrings;
If false, preserves blank line only if one exists before.
Default: optIn.forceBlankLineBeforeDocstring = true
object Stuff {
/** Some function */
def hello = ()
}
object Stuff {
/** Some function */
def hello = ()
}
Config for this example:
optIn.forceBlankLineBeforeDocstring = true
object Stuff {
/** Some function */
def hello = ()
}
object Stuff {
/** Some function */
def hello = ()
}
Config for this example:
optIn.forceBlankLineBeforeDocstring = false
rewriteTokens
Map of tokens to rewrite. For example, Map("⇒" -> "=>") will rewrite unicode arrows to regular ascii arrows.
Default: rewriteTokens = {}
val tuple = "a" -> 1
val lambda = (x: Int) => x + 1
for {
a <- Option(1)
b <- Option(2)
} yield a + b
val tuple = "a" → 1
val lambda = (x: Int) ⇒ x + 1
for {
a ← Option(1)
b ← Option(2)
} yield a + b
Config for this example:
rewriteTokens = {
"⇒": "=>"
"→": "->"
"←": "<-"
}
Edition
Removed in 2.7.0
Editions are no longer used. They were kept for backwards compatibility with old
configuration files but new changes to the default Scalafmt formatting behavior
will not respect the edition
setting.
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 = "2.7.5"
maxColumn = 80
docstrings.oneline = keep
docstrings.wrap = no
docstrings.blankFirstLine = no
docstrings.style = SpaceAsterisk
comments.wrap = no
comments.wrapStandaloneSlcAsSlc = false
optIn.configStyleArguments = true
optIn.breaksInsideChains = false
optIn.breakChainOnFirstMethodDot = true
optIn.encloseClassicChains = false
optIn.selfAnnotationNewline = true
optIn.annotationNewlines = true
optIn.forceBlankLineBeforeDocstring = true
optIn.blankLineBeforeDocstring = false
binPack.unsafeCallSite = false
binPack.unsafeDefnSite = false
binPack.parentConstructors = never
binPack.literalArgumentLists = true
binPack.literalsIncludeSimpleExpr = false
binPack.literalsSingleLine = false
binPack.literalsMinArgCount = 5
binPack.literalsInclude = [
".*"
]
binPack.literalsExclude = [
String
"Term.Name"
]
continuationIndent.callSite = 2
continuationIndent.defnSite = 4
continuationIndent.caseSite = 4
continuationIndent.ctorSite = null
continuationIndent.extendSite = 4
continuationIndent.withSiteRelativeToExtends = 0
continuationIndent.commaSiteRelativeToExtends = 2
align.multiline = false
align.stripMargin = true
align.openParenCallSite = false
align.openParenDefnSite = false
align.tokens = [
{
code = "=>"
owner = Case
}
]
align.arrowEnumeratorGenerator = false
align.ifWhileOpenParen = false
align.treeCategory."Defn.Trait" = "class/object/trait/enum"
align.treeCategory."Defn.Object" = "class/object/trait/enum"
align.treeCategory."Defn.Val" = "given/val/var/def"
align.treeCategory."Defn.Enum" = "class/object/trait/enum"
align.treeCategory."Defn.Def" = "given/val/var/def"
align.treeCategory."Defn.GivenAlias" = "given/val/var/def"
align.treeCategory."Defn.Var" = "given/val/var/def"
align.treeCategory."Enumerator.Generator" = for
align.treeCategory."Enumerator.Val" = for
align.treeCategory."Defn.Class" = "class/object/trait/enum"
spaces.beforeContextBoundColon = Never
spaces.afterTripleEquals = false
spaces.inImportCurlyBraces = false
spaces.inInterpolatedStringCurlyBraces = false
spaces.inParentheses = false
spaces.neverAroundInfixTypes = []
spaces.afterKeywordBeforeParen = true
spaces.inByNameTypes = true
spaces.afterSymbolicDefs = false
literals.long = Upper
literals.float = Lower
literals.double = Lower
literals.hexDigits = Lower
literals.hexPrefix = Lower
literals.scientific = Lower
lineEndings = unix
rewrite.rules = []
rewrite.redundantBraces.methodBodies = true
rewrite.redundantBraces.includeUnitMethods = true
rewrite.redundantBraces.maxLines = 100
rewrite.redundantBraces.stringInterpolation = false
rewrite.redundantBraces.parensForOneLineApply = null
rewrite.redundantBraces.generalExpressions = true
rewrite.redundantBraces.ifElseExpressions = false
rewrite.sortModifiers.order = [
implicit
final
sealed
abstract
override
private
protected
lazy
open
transparent
inline
infix
opaque
]
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.topLevelOnly = true
indentOperator.include = ".*"
indentOperator.exclude = "^(&&|\|\|)$"
newlines.source = null
newlines.avoidInResultType = false
newlines.neverBeforeJsNative = false
newlines.sometimesBeforeColonInMethodReturnType = true
newlines.penalizeSingleSelectMultiArgList = true
newlines.alwaysBeforeCurlyBraceLambdaParams = false
newlines.beforeCurlyLambdaParams = never
newlines.topLevelStatementsMinBreaks = 1
newlines.topLevelStatements = []
newlines.alwaysBeforeTopLevelStatements = false
newlines.afterCurlyLambdaParams = never
newlines.implicitParamListModifierForce = []
newlines.implicitParamListModifierPrefer = null
newlines.alwaysBeforeElseAfterCurlyIf = false
newlines.alwaysBeforeMultilineDef = false
newlines.beforeMultiline = null
newlines.beforeMultilineDef = null
newlines.afterInfix = null
newlines.afterInfixBreakOnNested = false
newlines.afterInfixMaxCountPerExprForSome = 10
newlines.afterInfixMaxCountPerFile = 500
newlines.avoidForSimpleOverflow = []
newlines.avoidAfterYield = true
runner.debug = false
runner.eventCallback = "<FormatEvent => Unit>"
runner.parser = "<Parse[Tree]>"
runner.optimizer.dequeueOnNewStatements = true
runner.optimizer.escapeInPathologicalCases = true
runner.optimizer.maxVisitsPerToken = 10000
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
includeNoParensInSelectChains = false
assumeStandardLibraryStripMargin = false
danglingParentheses.callSite = true
danglingParentheses.defnSite = true
danglingParentheses.ctrlSite = true
danglingParentheses.exclude = []
poorMansTrailingCommasInConfigStyle = false
trailingCommas = never
verticalMultiline.atDefnSite = false
verticalMultiline.arityThreshold = 100
verticalMultiline.newlineBeforeImplicitKW = false
verticalMultiline.newlineAfterImplicitKW = false
verticalMultiline.newlineAfterOpenParen = false
verticalMultiline.excludeDanglingParens = [
"`class`"
"`trait`"
]
verticalAlignMultilineOperators = false
onTestFailure = ""
encoding = "UTF-8"
project.git = false
project.files = []
project.includeFilters = [
".*\.scala$"
".*\.sbt$"
".*\.sc$"
]
project.excludeFilters = []
xmlLiterals.assumeFormatted = false