Any style guide written in English is either so brief that it’s ambiguous, or so long that no one reads it. -- Bob Nystrom, "Hardest Program I've Ever Written", Dart, Google.
Scalafmt turns the mess on the left into the (hopefully) readable, idiomatic and consistently formatted Scala code on the right.
object FormatMe { List(number) match
{ case head :: Nil
if head % 2 == 0 => "number is even"
case head :: Nil =>
"number is not even"
case Nil =>
"List is empty" }
function(arg1,
arg2(arg3(arg4,
arg5, "arg6")
, arg7 + arg8),
arg9.select(1, 2,
3, 4, 5, 6)) }
object FormatMe {
List(number) match {
case head :: Nil if head % 2 == 0 =>
"number is even"
case head :: Nil =>
"number is not even"
case Nil =>
"List is empty"
}
function(
arg1,
arg2(
arg3(arg4, arg5, "arg6"),
arg7 + arg8
),
arg9.select(1, 2, 3, 4, 5, 6)
)
}
The goal of scalafmt is to produce good enough formatted code so that you can focus on programming instead of manipulating syntax trivia. Scalafmt can be used in several environments such as the command line, text editors and build tools.
It is not a goal to format every single Scala source file under the sun. In particular, scalafmt cannot format deeply nested computer generated code.
Scalafmt is maintained by @olafurpg in his free time. Bug reports, feature requests, questions and PRs are welcome. Complaints and unfriendly attitude is not welcome.
Curious to learn more about scalafmt? Check out this talk:
scalafmt command line tool is with
Coursier.
NOTE To install Coursier see here
Create a standalone executable in /usr/local/bin/scalafmt with (sudo if necessary):
coursier bootstrap com.geirsson:scalafmt-cli_2.12:1.6.0-RC3 \
-r bintray:scalameta/maven \
-o /usr/local/bin/scalafmt --standalone --main org.scalafmt.cli.Cli
scalafmt --version # should be 1.6.0-RC3
Alternatively you can create a slim 15 KiB bootstrap script with:
coursier bootstrap com.geirsson:scalafmt-cli_2.12:1.6.0-RC3 \
-r bintray:scalameta/maven \
-o scalafmt --main org.scalafmt.cli.Cli
./scalafmt --version # should be 1.6.0-RC3
It is recommended to put this bootstrap script in your code repository
to make sure everyone on your team, as well as CI, uses the same scalafmt
version. To configure which files to format, see project.
To customize the JVM options, use the Coursier option --java-opt, more info with
coursier bootstrap --help | grep -A 1 "\-\-java-opt"
If you use coursier to install a pre-release, be sure to include the flag -r bintray:scalameta/maven
so that the artifact can be resolved.
If you use sbt to install a pre-release, be sure to add the following setting
resolvers += Resolver.bintray("scalameta", "maven")
scalafmt with a
text editor like vim/Emacs/Atom/Sublime/VS Code.
brew install nailgun./usr/local/bin/scalafmt_ng with (sudo if necessary)
coursier bootstrap --standalone com.geirsson:scalafmt-cli_2.12:1.6.0-RC3 \
-r bintray:scalameta/maven \
-o /usr/local/bin/scalafmt_ng -f --main com.martiansoftware.nailgun.NGServer
scalafmt_ng & // start nailgun in background
ng ng-alias scalafmt org.scalafmt.cli.Cli
ng scalafmt --version # should be 1.6.0-RC3
Nailgun keeps scalafmt running on a local server to avoid the JVM startup penalty and also so scalafmt can benefit from JIT. This makes scalafmt up to 10x faster when formatting a single file from the CLI. The downside to Nailgun is that the setup is complicated and the long-running server needs to be restarted once in awhile.
brew install --HEAD olafurpg/scalafmt/scalafmt
scalafmt --version // should be 1.6.0-RC3
// to upgrade between releases
brew upgrade scalafmt
master branch and
may include flags that have not been published yet.
build commit: 4b198a1865f62c73e8930522274ecc323d203135
build time: Mon Jun 11 14:02:12 UTC 2018
scalafmt 1.6.0-RC3-1-4b198a18
Usage: scalafmt [options] [<file>...]
-h, --help prints this usage text
-v, --version print version
<file>... file or directory, in which case all *.scala files are formatted.
--stdout write formatted files to stdout
--git <value> if true, ignore files in .gitignore (default false)
--exclude <value> file or directory, in which case all *.scala files are formatted.
-c, --config <value> a file path to .scalafmt.conf.
--config-str <value> configuration defined as a string
--stdin read from stdin and print to stdout
--no-stderr don't use strerr for messages, output to stdout
--assume-filename <value>
when using --stdin, use --assume-filename to hint to scalafmt that the input is an .sbt file.
--test test for mis-formatted code, exits with status 1 on failure.
--migrate2hocon <value> migrate .scalafmt CLI style configuration to hocon style configuration in .scalafmt.conf
--diff If set, only format edited files in git diff against master.
--diff-branch <value> If set, only format edited files in git diff against provided branch.
--build-info prints build information
--quiet don't print out stuff to console.
--debug print out diagnostics to console.
--non-interactive disable fancy progress bar, useful in ci or sbt plugin.
Examples:
scalafmt # Format all files in the current project, configuration is determined in this order:
# 1. .scalafmt.conf file in current directory
# 2. .scalafmt.conf inside root directory of current git repo
# 3. no configuration, default style
scalafmt --test # throw exception on mis-formatted files, won't write to files.
scalafmt --diff # Format all files that were edited in git diff against master branch.
scalafmt --diff-branch 2.x # same as --diff, except against branch 2.x
scalafmt --stdin # read from stdin and print to stdout
scalafmt --stdin --assume-filename foo.sbt < foo.sbt # required when using --stdin to format .sbt files.
scalafmt Code1.scala A.scala # write formatted contents to file.
scalafmt --stdout Code.scala # print formatted contents to stdout.
scalafmt --exclude target # format all files in directory excluding target
scalafmt --config .scalafmt.conf # read custom style from file
scalafmt --config-str "style=IntelliJ" # define custom style as a flag, must be quoted.
Please file bugs to https://github.com/scalameta/scalafmt/issues
Settings > PluginsBrowse repositoriesscalafmt
The default shortcut is Ctrl + Shift + L.
Undo works, but not redo.
The plugin determines which style to use in this order:
.scalafmt.conf in the project's root directory, if it exists$HOME/.scalafmt.conf, if it existsdefault style..scalafmt.conf should look like, see
Configuration.
The scalafmt IntelliJ plugin has a "Format on save" setting.
NOTE. You may need to enable balloons to get error message: Settings > Appearance & Behavior > Notifications > Scalafmt > Popup "Balloon". You need to first check "Display Balloon Notifications".
// In project/plugins.sbt. Note, does not support sbt 0.13, only sbt 1.0.
addSbtPlugin("com.geirsson" % "sbt-scalafmt" % "1.6.0-RC3")
The sbt plugin is enabled by default for the Test and Compile configurations.
To enable the plugin for integration tests
inConfig(IntegrationTest)(scalafmtConfigSettings)
and then use it:scalafmt to format.
Pro tip. To share configuration across projects, you can define a setting
in build.sbt to generate .scalafmt.conf programmatically on sbt load.
// define setting key to write configuration to .scalafmt.conf
SettingKey[Unit]("scalafmtGenerateConfig") :=
IO.write( // writes to file once when build is loaded
file(".scalafmt.conf"),
"""style = IntelliJ
|# Your configuration here
""".stripMargin.getBytes("UTF-8")
)
lucidsoftware/neo-sbt-scalafmt is an sbt plugin that
update resolutions mechanism, which tends to be
slow for large multi-module builds.
.vimrc
noremap <F5> :Autoformat<CR>
let g:formatdef_scalafmt = "'scalafmt --stdin'"
let g:formatters_scala = ['scalafmt']
libraryDependencies += "com.geirsson" %% "scalafmt-core" % "1.6.0-RC3"
// Scala.js
libraryDependencies += "com.geirsson" %%% "scalafmt-core" % "1.6.0-RC3"
Use the API like this
scala> org.scalafmt.Scalafmt.format("""
object FormatMe { List(Split(Space, 0).withPolicy(SingleLineBlock(close)), Split(Newline, 1).withPolicy{ case Decision(t@FormatToken(_, `close`, _), s) => Decision(t, List(Split(Newline, 0)))}.withIndent(2, close, Right)) }
""").get
res0: java.lang.String =
"object FormatMe {
List(
Split(Space, 0).withPolicy(SingleLineBlock(close)),
Split(Newline, 1)
.withPolicy {
case Decision(t @ FormatToken(_, `close`, _), s) =>
Decision(t, List(Split(Newline, 0)))
}
.withIndent(2, close, Right)
)
}
"
Obtain a configuration object with parseHoconConfig
scala> val config = org.scalafmt.Scalafmt.parseHoconConfig("align=most").get
scala> org.scalafmt.Scalafmt.format("""
object Align {
val x = 1
val xx = 2
}""", config).get
res0: java.lang.String =
"object Align {
val x = 1
val xx = 2
}
"
To format code with top-level statements like *.sbt files
scala> val base = org.scalafmt.Scalafmt.parseHoconConfig("align=most").get
scala> val config = org.scalafmt.Scalafmt.configForSbt(base)
scala> org.scalafmt.Scalafmt.format("""
val x = 1
val xx = 2
""", config).get
res0: java.lang.String =
"val x = 1
val xx = 2
"
org.scalafmt.Scalafmt.
In particular, case classes in org.scalafmt.config are subject to binary and
source breaking changes on any release.
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.
ScalafmtConfig instance, which is set to ScalafmtStyle.default
by default.
// docstrings = ScalaDoc
/** Align by second asterisk.
*
*/
// docstrings = JavaDoc
/** Align by first asterisk.
*
*/
If true, the margin character | is aligned with the opening triple
quote """ in interpolated and raw string literals.
// 40 columns |
object StripMargin {
val example1 =
s"""Examples:
| * one
| * two
| * $three
|""".stripMargin
// pipe character after opening """
val example2 =
s"""|Examples:
| * one
| * two
| * $three
|""".stripMargin
}
Example:
function(
argument1 // indented by 2
)
Same as continuationIndent.callSite except for definition site.
Example:
def function(
argument1: Type1): ReturnType // Indented by 4
x match { // true for case arrows
case 2 => 22
case 22 => 222
}
def foo(
a: Int, // true for defn site open paren
b: String
): Int
foo(
a: Int, // true for call site open paren
b: String
): Int
val x = 2 // false for assignment
val xx = 22
case object B extends A // false for `extends`
case object BB extends A
x match { // false for case arrows
case 2 => 22 // also comments!
case 22 => 222 // don't align me!
}
def foo(
a: Int, // false for defn site
b: String
): Int
foo(
a: Int, // false for call site
b: String
): Int
Pro tip: Enable this setting to minimize git diffs/conflicts from renamings and other refactorings.
align.tokens = [] align.ifWhileOpenParen = false
val x = 2 // true for assignment
val xx = 22
case object B extends A // false 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
yy <- List(2)
} yield x ** xx
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"
)
align.tokens = [
{
code = "←"
owner = "Enumerator.Generator"
}
{
code = "%"
owner = "Term.ApplyInfix"
}
{
code = "{"
owner = Template
}
{
code = "⇒"
owner = Case
}
{
code = extends
owner = "Defn.(Class|Trait|Object)"
}
{
code = "→"
owner = "Term.ApplyInfix"
}
{
code = "="
owner = "(Enumerator.Val|Defn.(Va(l|r)|Def|Type))"
}
{
code = "<-"
owner = "Enumerator.Generator"
}
{
code = "//"
owner = ".*"
}
{
code = "->"
owner = "Term.ApplyInfix"
}
{
code = "%%"
owner = "Term.ApplyInfix"
}
{
code = "=>"
owner = Case
}
{
code = "}"
owner = Template
}
{
code = "%%%"
owner = "Term.ApplyInfix"
}
]for {
// align <- with =
x <- List()
yy = 2
// aligns body by arrow
zzz <- new Integer {
def value = 3
}
} yield x
// Note. Only for the truest vertical aligners. This is a new option,
// feel free to open PR enabling more crazy vertical alignment here.
// Expect changes.
align.tokens = [
{
code = "←"
owner = "Enumerator.Generator"
}
{
code = "%"
owner = "Term.ApplyInfix"
}
{
code = "{"
owner = Template
}
{
code = "⇒"
owner = Case
}
{
code = extends
owner = "Defn.(Class|Trait|Object)"
}
{
code = "→"
owner = "Term.ApplyInfix"
}
{
code = "="
owner = "(Enumerator.Val|Defn.(Va(l|r)|Def|Type))"
}
{
code = "<-"
owner = "Enumerator.Generator"
}
{
code = "//"
owner = ".*"
}
{
code = "->"
owner = "Term.ApplyInfix"
}
{
code = "%%"
owner = "Term.ApplyInfix"
}
{
code = "=>"
owner = Case
}
{
code = "}"
owner = Template
}
{
code = "%%%"
owner = "Term.ApplyInfix"
}
]
align.arrowEnumeratorGenerator = true
align.tokenCategory.Equals = Assign
align.tokenCategory.LeftArrow = Assign
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.
NOTE. It is valid to set align.tokens = more to re-use settings
from align=more. Same applies for none/some/most.
// =======================================================
// scalafmt: {align.tokens = [{code = "=>", owner = "Case"}]}
// =======================================================
x match {
case 1 => 1 -> 2
case 11 => 11 -> 22
}
// =======================================================
// scalafmt: {align.tokens = ["%", "%%"]}
// =======================================================
val x = List(
"org.scala-lang" % "scala-compiler" % scalaVersion.value,
"com.lihaoyi" %% "sourcecode" % "0.1.1"
)
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"
To learn more about Scalameta, see this tutorial.
// align.arrowEnumeratorGenerator = false
for {
x <- new Integer {
def value = 2
}
} yield x
// align.arrowEnumeratorGenerator = true
for {
x <- new Integer {
def value = 2
}
} yield x
// Column limit |
// align.openParenCallSite = true
foo(arg1, arg2)
function(arg1, // align by (
arg2,
arg3)
function(
argument1,
argument2)
// align.openParenCallSite = false
foo(arg1, arg2)
function(
arg1, // no align by (
arg2,
arg3)
function(
argument1,
argument2)
// align.openParenDefnSite = true
// Column limit |
class IntString(int: Int, string: String)
class IntStringLong(int: Int,
string: String,
long: Long)
// align.openParenDefnSite = false
// Column limit |
class IntString(int: Int, string: String)
class IntStringLong(
int: Int,
string: String,
long: Long
)
newlines.* options are used to configure when and where scalafmt should
insert newlines.
// newlines.alwaysBeforeTopLevelStatements = false
import org.scalafmt
package P {
object O {
val x1 = 1
val x2 = 2
def A = "A"
def B = "B"
}
}
// newlines.alwaysBeforeTopLevelStatements = true
import org.scalafmt
package P {
object O {
val x1 = 1
val x2 = 2
def A = "A"
def B = "B"
}
}
// Column limit |
// newlines.sometimesBeforeColonInMethodReturnType = true
implicit def validatedInstances[E](implicit E: Semigroup[E])
: Traverse[Validated[E, ?]] with ApplicativeError[Validated[E, ?], E] = 2
// newlines.sometimesBeforeColonInMethodReturnType = false
implicit def validatedInstances[E](implicit E: Semigroup[E]): Traverse[
Validated[E, ?]] with ApplicativeError[Validated[E, ?], E] = 2
// newlines.penalizeSingleSelectMultiArgList = true
logger.elem(a,
b,
c)
// newlines.penalizeSingleSelectMultiArgList = false
logger
.elem(a, b, c)
See this comment for further motivation.
// newlines.alwaysBeforeElseAfterCurlyIf = true
if(someCond) {
foo()
}
else {
bar()
}
// newlines.alwaysBeforeElseAfterCurlyIf = false
if(someCond) {
foo()
} else {
bar()
}
To enable a rewrite rule, add it to the config like this rewrite.rules = [SortImports].
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)
rewrite.rules = [ avoidinfix ]
rewrite.neverInfix.
import a.{
b,
c
}, h.{
k, l
}
import d.e.{f, g}
import a.{
foo => bar,
zzzz => _,
_
}
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 => _, _}
rewrite.rules = [ expandimportselectors ]
object RedundantBraces {
def foo = {
List(1, 2, 3).sum
}
// stringInterpolation = true
q"Hello ${name}"
}object RedundantBraces {
def foo =
List(1, 2, 3).sum
// stringInterpolation = true
q"Hello $name"
}
rewrite.rules = [ redundantbraces ] rewrite.redundantBraces.stringInterpolation = true
rewrite.redundantBraces.maxLines = 100rewrite.redundantBraces.includeUnitMethods = truerewrite.redundantBraces.stringInterpolation = truerewrite.redundantBraces.generalExpressions = false
(disabled by default due to #1147)
Removes redundant parentheses in guard clauses.
object RedundantParenthesis {
def c(b: List[Int]): List[Int] =
for {
a <- b
if (a.nonEmpty)
} yield a
}
object RedundantParenthesis {
def c(b: List[Int]): List[Int] =
for {
a <- b
if a.nonEmpty
} yield a
}
rewrite.rules = [ redundantparens ]
The imports are sorted by the groups: symbols, lower-case, upper-case.
import foo.{Zilch, bar, Random, sand}
import foo.{bar, sand, Random, Zilch}
rewrite.rules = [ sortimports ]
The imports are sorted by their Ascii codes
import foo.{~>, `symbol`, bar, Random}
import foo.{Random, `symbol`, bar, ~>}
rewrite.rules = [ asciisortimports ]
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.
//before
final lazy private implicit val x = 42
lazy final implicit private val y = 42
//after
private final implicit lazy val x = 42
private final implicit lazy val y = 42
//before
class Test(
implicit
final private val i1: Int,
private final val i2: String
)
//after
class Test(
implicit
private final val i1: Int,
private final val i2: String
)
//before
object X {
sealed protected[X] trait ADT
final private case object A1 extends ADT
private final case class A2(x: Int) extends ADT
}
//after
object X {
protected[X] sealed trait ADT
private final case object A1 extends ADT
private final case class A2(x: Int) extends ADT
}
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.
Example config:
rewrite {
rules = [SortModifiers]
#optional, see default values below
sortModifiers {
order = ["implicit", "final", "sealed", "abstract",
"override", "private", "protected", "lazy"]
}
}
Default values:
rewrite.sortModifiers.order = ["implicit", "final", "sealed", "abstract", "override", "private", "protected", "lazy"]
Replaces parentheses into curly braces in for comprehensions that contain multiple enumerator generators.
object a {
for(a <- as; b <- bs if b > 2)
yield (a, b)
}
object a {
for {
a <- as
b <- bs if b > 2
} yield (a, b)
}
rewrite.rules = [ prefercurlyfors ]
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.
object a {
def format(code: String, age: Int)(implicit ev: Parser, c: Context): String
}
object a {
def format(
code: String,
age: Int
)(implicit ev: Parser,
c: Context
): String
}
maxColumn = 60 verticalMultiline.atDefnSite = true
The default configuration options are
verticalMultiline.atDefnSite = false
verticalMultiline.arityThreshold = 100
verticalMultiline.newlineBeforeImplicitKW = false
verticalMultiline.newlineAfterImplicitKW = false
verticalMultiline.newlineAfterOpenParen = false
verticalMultiline.excludeDanglingParens = [
class
trait
]
If true, enable vertical multiline formatting as described above.
If set, this will trigger a vertical multi-line formatting even though the definition falls below the maxColumn width.
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
}
verticalMultiline.atDefnSite = true verticalMultiline.arityThreshold = 2
If true, add a newline after the opening paren of a parameter list. This can be used to control the formatting of methods that have multiple parameter lists.
object a {
def other(a: String, b: String)(c: String) = a + b + c
}
object a {
def other(
a: String,
b: String
)(
c: String
) = a + b + c
}
continuationIndent.defnSite = 2 verticalMultiline.atDefnSite = true verticalMultiline.arityThreshold = 2 verticalMultiline.newlineAfterOpenParen = true
object a {
def format(code: String, age: Int)(implicit ev: Parser, c: Context): String
}
object a {
def format(
code: String,
age: Int
)(
implicit ev: Parser,
c: Context
): String
}
maxColumn = 60 verticalMultiline.atDefnSite = true verticalMultiline.newlineBeforeImplicitKW = true
object a {
def format(code: String, age: Int)(implicit ev: Parser, c: Context): String
}
object a {
def format(
code: String,
age: Int
)(implicit
ev: Parser,
c: Context
): String
}
maxColumn = 60 verticalMultiline.atDefnSite = true verticalMultiline.newlineAfterImplicitKW = true
This setting defines which cases should be allowed to have dangling parens.
case class Bar(x: String, y: String)
case class Bar(
x: String,
y: String
)
continuationIndent.defnSite = 2 verticalMultiline.atDefnSite = true verticalMultiline.arityThreshold = 2 verticalMultiline.excludeDanglingParens = []
If true, add a newline before the body of a multiline def without curly braces.
object a {
def foo(bar: Bar): Foo = bar
.flatMap(f)
.map(g)
}
object a {
def foo(bar: Bar): Foo =
bar
.flatMap(f)
.map(g)
}
maxColumn = 60 verticalMultiline.atDefnSite = true
// format: OFF blocks:
object PrettyMatrix {
// format: off
val identity = Array(1, 0, 0,
0, 1, 0,
0, 0, 1)
// format: on
}
To disable formatting for a whole file, put the comment at the top of
the file.
// format: OFF.// @formatter:off and // @formatter:on
will also work, for compatibility with the IntelliJ formatter.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
]
preserve output will include endings included in original file (windows if there was at least one windows
line ending, unix if there was zero occurrences of windows line endings)unix output will include only unix line endingswindows output will include only windows line endings
// 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, 0, 1, 1, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1,
0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 1)
// binPack.literalArgumentLists = false
val secret: List[Bit] = List(
0,
0,
1,
1,
// really long list...
1
)
// column limit |
// binPack.parentConstructors = false
object DefaultStyle
extends Parent
with SecondParent
with ThirdParent {
// body ...
}
// column limit |
// binPack.parentConstructors = true
object DefaultStyle
extends Parent with SecondParent
with ThirdParent {
// body ...
}
// spaces.afterKeywordBeforeParen = true
if (a) foo()
while (a) foo()
for (a <- as) foo()
// spaces.afterKeywordBeforeParen = false
if(a) foo()
while(a) foo()
for(a <- as) foo()
// spaces.afterSymbolicDefs = true
trait Test[A] {
def <=> [B](that: Test[B]): Int
}
// spaces.afterSymbolicDefs = false
trait Test[A] {
def <=>[B](that: Test[B]): Int
}
// includeCurlyBraceInSelectChains = true
List(1)
.map { x =>
x + 2
}
.filter(_ > 2)
// includeCurlyBraceInSelectChains = false
List(1).map { x =>
x + 2
}.filter(_ > 2)
For more details, see
this comment.
If true, forces a select chain (pipeline) to break if there is a newline at the start of the chain.
// original
foo
.map(_ + 1)
.filter(_ > 2)
// optIn.breakChainOnFirstMethodDot = true
foo
.map(_ + 1)
.filter(_ > 2)
// optIn.breakChainOnFirstMethodDot = false
foo.map(_ + 1).filter(_ > 2)
// note. chain starts at .foo() in a.b.foo()
See this comment for further motivation.
Set to -1 to disable. Increase number to require bigger argument
bodies to trigger flag.
// Before: Argument body is too big
Account(userName = "user",
fullName = "user@localhost",
mailAddress = "",
password = "",
isAdmin = false,
url = None,
registeredDate = new Date(),
updatedDate = new Date(),
lastLoginDate = None,
image = image,
isGroupAccount = false,
isRemoved = false)
// After: "config style"
Account(
userName = "user",
fullName = "user@localhost",
mailAddress = "",
password = "",
isAdmin = false,
url = None,
registeredDate = new Date(),
updatedDate = new Date(),
lastLoginDate = None,
image = image,
isGroupAccount = false,
isRemoved = false
)
Set runner.optimizer.forceConfigStyleMinArgCount = 1 to enable
this rule for function calls with only 1 argument
(default = 2).
By forcing config style, scalafmt is able to greatly optimize performance eliminating a large number of "search state exploded" errors. See these flame graphs.
// Column 40 |
// non bin packed parent constructors
object DefaultStyle
extends Parent
with SecondParent
with ThirdParent {
// non bin packed arguments
function(
argument1,
argument2(argument3, argument4)
)
// Vertical alignment only for case arrows
x match {
case 1 => 1
case 11 => 1
}
}
Option 2: IntelliJ
// Column 40 |
// non bin packed parent constructors
object IntelliJStyle
extends Parent
with SecondParent
with ThirdParent {
function(argument1, argument2)
// continuationIndent = 2 # for call + defn site
// align.openParenCallSite = false
// danglingParentheses = true
function(
argument1,
argument2,
argument3,
argument4
)
// openParenCallSite = true
def foobar(
argument1: Type1,
argument2: Type2
): Int = argument1 + argument2
}
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.6.0-RC3"
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
be
taggedAs
thrownBy
synchronized
have
when
size
]
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 = []
Scalafmt tries to automatically reformat as much as possible. However, sometimes you need to help scalafmt decide how to format your code.
a + b
instead of a.+(b).
Scalafmt preserves your line breaks in infix applications, even if this
means the maxColumn setting is not respected.
// column limit |
// if you have long infix appplications
a.b(c) && d.e(f, g, h)
// then scalafmt may format like this
a.b(c) && d.e(
f, g, h)
// which is ugly. You can fix it by inserting
// a newline after && and it will look like this
a.b(c) &&
d.e(f, g, h)
// Put newline after opening (
// and newline before closing )
// to force one argument on each line.
// OK: Config style
function(
longerArg1 = defaultValue1,
longerArg2 = defaultValue2,
longerArg3 = defaultValue3
)
// NOT Config style
function(longerArg1 = defaultValue1,
longerArg2 = defaultValue2,
longerArg3 = defaultValue3)
Here are the download numbers for the IntelliJ plugin.
maxColumn setting, which
I personally like and is present in many popular coding styles.My benchmarks show that scalafmt is for most common cases around 4-6x slower than scalariform (btw, scalariform is already impressively fast). This means that formatting your average 1.000 LOC file on modern hardware will take around 200ms, which should still feel close enough to instant.
The main feature that makes scalafmt slower than scalariform is the column-width limit. To figure the "best" way to break a long line, Scalafmt may try thousands of different formatting solutions.
I am sure that scalafmt could benefit greatly from micro optimizations. Any help here is appreciated.
That's not a question, but I agree that code formatters like scalafmt do sometimes increase the size of diffs in code reviews. I still believe it's worth it, considering
?w=1 to the URL to ignore whitespace changes.git blame has a -w flag to ignore whitespace changes
so you can still blame your colleagues for their crappy code.align=none
If alignment is enabled a renaming of one entity can impact the indentation of other entities.danglingParenthesis=true
Having the closing parenthesis on the same line as the last argument makes the diff line include
the parenthesis and everything following it in case that argument is renamed.
So, technically this does not reduce the number of diff lines, but the length of them.
Developing code formatters is notoriously hard and scalafmt has been no exception. The following are the biggest known issues with scalafmt:
AKA. "Search state exploded"
0.5.0 made big improvements on this issue. In my test corpus, only 13 out of 27.000 source files trigger this error now.
Scalafmt cannot yet format all files with deeply nested functions calls. Deeply nested code is troublesome because the number of possible formatting options grows exponentially with each new layer of nesting. Instead of taking seconds or minutes to complete formatting, scalafmt chooses to bail early and leave the source file unformatted.
There are two workaround if you are affected by this issue:
align.openParenCallSite = false to shrink the search
space.Other cool code formatters like ClangFormat, dartfmt and rfmt use better techniques to solve this issue, which scalafmt can maybe learn from.
In my test corpus, as of v0.5.0, only 12 files out of 27.000 source files are affected by this issue. If sources are already formatted by scalafmt, no source file in the test corpus triggers non-idempotent formatting.
Pro tip. As awkward as I feel recommending this, you may want to run scalafmt twice on your codebase for the first time you reformat it.
rewrite.redundantBraces.generalExpressions = false by default until #1143 is fixed.optIn.blankLineBeforeDocstring setting..sc.RedundantBraces to remove redundant braces from
all expressions. If you'd like to restrict RedundantBraces behaviour
to just method bodies and/or string interpolation as it was before this
change, you can do so via new setting:
rewrite.redundantBraces.generalExpressions = falsemaxColumn.
// maxColumn |
// before
Foo with Bar with Baz
// after
Foo
with Bar
with BazNewlines.alwaysBeforeMultilineDef=true.
If true, add a newline before the body of a multiline def without
curly braces. For example,
// before
def foo(bar: Bar): Foo = bar
.flatMap(f)
.map(g)
// newlines.alwaysBeforeMultilineDef = false
def foo(bar: Bar): Foo = bar
.flatMap(f)
.map(g)
// newlines.alwaysBeforeMultilineDef = true (default, unchanged from 1.4)
def foo(bar: Bar): Foo =
bar
.flatMap(f)
.map(g)Big thanks to all contributors!
See merged PRs.
indentOperator config,
by @daddykotex.project.git = true, by @lloydmeta.spaces.inByNameTypes=false option to format
def foo(a: => A) as def foo(a: =>A).
By @vovapolu, thanks to ENSIME sponsorship fund.encoding option when writing files, by @alexdupreoptIn.breaksInsideChains = true option, by @olafurpgSee merged PRs.
org.scalafmt.internal and
org.scalafmt.config.
maxColumn has now been fixed, #976.
Expect significant diffs from upgrading to this version.
To get the previous behavior, set maxColumn=n-1 if you previously
enabled maxColumn=n.runner.dialect to format files using new Scala syntax such as
trailing commas, inline keyword, literal types, trait parameters.case pattern matching are now vertically aligned.
Concretely,
align.tokens = [caseArrow] by default now, it was align.tokens = [] before.
This decision was voted upon on in #890 with 23 votes in favor and
9 votes against.-i by default, to get the old behavior
pass in the flag --stdout, by @pjrt.--files flag is now optional, this means scalafmt Foo.scala
will write the formatted output into that file, by @pjrt.optIn.annotationNewlines = true by default now, it was false.
See #942 for motivation.spaces.beforeContextBoundColon = IfMultipleBounds is now supported,
see #916, by @hejfelix.newlines.alwaysBeforeTopLevelStatements = true now skips nested blocks,
see #933, by @Daxten.bestEffortInDeeplyNestedCode has been removed. This option was unsafe
and a maintenance burden. See Deeply nested code for possible workarounds.Coursier is now the only recommended way to install the command-line application for Linux, Mac and Windows. With coursier can benefit from
I admit that the long coursier command is harder to remember than
homebrew upgrade scalafmt.
Please pitch your ideas here
on how to make installing command line apps with coursier as easy as
coursier install/upgrade scalafmt!
This change brings new opportunities to add new features to the
sbt plugin, for example reformatOnCompile if someone is motivated
to contribute that feature.
Note, I want to stress that sbt 1.0 brings incredible new opportunities for Scala tooling. Scalameta, which scalafmt uses for parsing, does not support Scala 2.10, which sbt 0.13 plugins are required to run on. I highly recommend you try to upgrade your build to sbt 1.0 as soon as possible.
// newlines.afterImplicitKWInVerticalMultiline = true
// newlines.beforeImplicitKWInVerticalMultiline = true
def format(
code: String,
age: Int
)(
implicit
ev: Parser,
c: Context
): String
// newlines.afterImplicitKWInVerticalMultiline = true
// newlines.beforeImplicitKWInVerticalMultiline = false
def format(
code: String,
age: Int
)(implicit
ev: Parser,
c: Context
): String
Thank you @sugakandrey for contributing this new feature!binPack.lambdaParameters = false by default. This fixes
issues like #719 and #716. The option will be removed in
v1.03 million lines reformatted with 0.6.1 compared to 0.5.8: scala-repos#20
Some formatting issues surfaced in the test suite when running on 2.12. These changed were related to byte literals and backtick identifiers. The issues in the test-suite were fixed, but I suspect other issues may appear in the wild when running on 2.12. If you notice unexpected changes with using scalafmt on 2.12, please report an issue.
runner.ignoreWarnings = true.scalafmt --test
fails. This can be helpful to explain to contributors on how to run
scalafmt for your project, for example "Run ./bin/scalafmt to fix this
issue.
To add a custom message, add onTestFailure = "To fix this error, run XXX".-Dfile.encoding.
To change, edit encoding = latin1.// indent.rightAssociativeInfixOperatorsLikeLeftAssociative = true (default)
a ::
b ::
c ::
d
// indent.rightAssociativeInfixOperatorsLikeLeftAssociative = false (old default)
a ::
b ::
c ::
dproject.excludeFilters.runner.dialectnewlines.sometimesBeforeColonInMethodReturnType now works the
same for vals, parameterless defs and def with regular parameters.runner.dialectscalafmt --diff should now handle better removed and unstaged files.
You should be able to put scalafmt --diff into your .git/hooks/pre-commit.rewrite.redundantBraces.stringInterpolation = false.
See RedundantBraces.
Thank you @ysusuk for contributing this feature!// if false (default)
def format_(implicit ev: Parse[T], ex: D): String = 1
// if true
def format_(implicit ev: Parse[T],
ex: D
): String = 1
Thank you @pjrt for contributing this feature!optIn.annotationNewlines = false. Thank you @mpociecha
for suggesting this flag!default style has been updated for prettier formatting output
and greater performance (less "search state exploded").
Highlights:
optIn.breakChainOnFirstMethodDot = true, was false.
See optIn.breakChainOnFirstMethodDot.
Thank you @stefanobaghino for contributing this flag!includeCurlyBraceInSelectChains = true, was false.
See includeCurlyBraceInSelectChains.
Thank you @rcavalcanti for suggesting this flag!binPack.literalArgumentLists = true, was false.
See binPack.literalArgumentLists.
Thank you @RatanRSur and @densh for suggesting this feature!newlines.penalizeSingleSelectMultiArgList = true, was false.
See newlines.penalizeSingleSelectMultiArgList.runner.optimizer.forceConfigStyleOnOffset = 150, was -1.
See runner.optimizer.forceConfigStyleOnOffset.For a more detailed overview of the new style differences, see this issue.
I did my best to make it possible to opt-out of the most dramatic changes. Still, v0.5 may have some minor diffs which are not configurable.
.scalafmt.conf in the root directory of your repo.
In particular, see project on how to define which
files should be formatted.
project.excludeFilters = ["target/"] should be enough for
most cases.
See sbt for a tip/workaround on how you can still define
configuration via sbt.reformatOnCompileSettings is no longer provided as part of the
sbt plugin. See sbt for a DIY workaround.--diff flag to CLI to only format files in the git
diff against master branch. See --help for more details.--diff-branch <branch-name> flag to CLI to only
format files in the git diff against branch <branch-name>.style = IntelliJ
optIn.configStyleArguments = true
meaning you can force line breaks. See #593 for more details.
Thanks @lihaoyi for the discussion/suggestion.indentYieldKeyword = true. See #592
for motivation. Thanks @lihaoyi for the suggestion.However, the tests are still failing on Windows. Help to improve this is welcome!
importSelectors = noBinPack that replaces
binPackImportSelectors = false to support a new third option
importSelectors = singleLine that keeps all import
selectors on a single line.
Thank you @mtomko for contributing this feature!
The flag binPackImportSelectors is now deprecated and will
be removed in 0.5.scalafmt-bootstrap that is an experiment to support
defining version = 1.6.0-RC3 in .scalafmt.conf.
The idea is to allow editor integrations (such as IntelliJ plugin)
to dynamically use a specific scalafmt version for a specific project.
This might also help solve the SBT plugin issue #485.
includeCurlyBraceInSelectChains = false.
// false (has been default so far, will stay default until 0.5)
Repositories.filter { t =>
(t.originUserName === userName.bind) &&
(t.originRepositoryName === repositoryName.bind)
}.sortBy(_.userName asc).map(t => t.userName -> t.repositoryName).list
// true (will become default in 0.5.0)
Repositories
.filter { t =>
(t.originUserName === userName.bind) &&
(t.originRepositoryName === repositoryName.bind)
}
.sortBy(_.userName asc)
.map(t => t.userName -> t.repositoryName)
.list
Here is a huge diff
for more examples of how this flag works.newlines.neverInResultType = false, which is used in Scala.js style.RedundantBraces where scalafmt would fail to format
due to parse error.--config flag when reading relative path using nailgun.--assume-filename flag in CLI to format .sbt files with --stdin.--stdin now.scalafmt (without flags)
will read configuration from .scalafmt.conf at the root of your git repo or current directory and
then format all files in your entire project or current directory.
You opt into the git integration by setting project.git = true.
You exclude files with project.excludeFilters = [regex1, regex2].
For more details, refer to the brand new --help section.
I hope to make this feature stable by 0.5, all feedback is very welcome. I plan to replace the current logic in the SBT plugin to figure out which files to format with this new feature.
If you are interested in having this feature work with other VCS like mercurial, don't hesitate to introduce yourself in the Gitter channel.
NOTE. I realised after releasing 0.4.5 that I forgot to
expose the --stdin flag that replaces the previous behavior of running
scalafmt (without flags). If you rely on reading from stdin you need to wait
until 0.4.6, sorry.
scalafmt bash script that can upgrade itself, see (EDIT: removed)
Linux/OSX section.
Thank you @hntd187!runner.fatalWarnings = true (only respected in CLI for now)
to throw an exception for warnings like parse errors or "Search state exploded".align.tokens.add = [foo] to add align
tokens on top of the existing align tokens in your base style.// before (note lack of indent)
val m.Term.New(
m.Template(Nil,
Seq(mparent),
m.Term.Param(Nil, m.Name.Anonymous(), None, None),
None)) =
lapply.toMtree[m.Term.New]
// after (note 2 space indent)
val m.Term.New(
m.Template(Nil,
Seq(mparent),
m.Term.Param(Nil, m.Name.Anonymous(), None, None),
None)) =
lapply.toMtree[m.Term.New]spacesInImportCurlyBraces, see #454.
Thank you @hasumedic!0.4.3 where a class not found exception was thrown
on parse error, see #492.--migrate2hocon now migrates --indentOperators false
to indentOperator = spray.--migrate2hocon now migrates rewriteTokens..scalafmt
to the new style in .scalafmt.conf, run
scalafmt --migrate2hocon .scalafmt with the CLI.
For super easy CLI installation in OSX and Linux, download the new
auto-upgrade script in (EDIT: removed) Linux/OSX section.// scalafmt: { maxColumn = 200 }
// OR
/*
scalafmt: {
maxColumn = 200
style = defaultWithAlign
}
*/
object Foo {
... // configuration is applied to remainder of file
}
Why? This can be useful
// scalafmt: ....
This feature does not give you an excuse to change you mind about the configuration on every single line of code.
Use this feature for good.ScalafmtStyle is now called ScalafmtConfig and belongs
to the org.scalafmt.config package (was previously in
org.scalafmt).FormatResult is now called Formatted and it has a
toEither method.Scalafmt.format no longer accepts a ScalafmtRunner argument,
instead the runner is now a member of ScalafmtConfig.ScalafmtStyle, you can consult
this testcase
or the --migrate2hocon implementation
here.
Don't hesitate to ask questions on gitter if you're unsure where your old
settings have moved.target.--exclude to exclude a set of directories.optIn.breakChainOnFirstMethodDot.
// Original before running scalafmt
List(1, 2, 3)
.map(_ + 1).filter(_ > 2)
// false (default)
List(1, 2, 3).map(_ + 1).filter(_ > 2)
// true
List(1, 2, 3)
.map(_ + 1)
.filter(_ > 2)
// Note, only the dot before the first method call triggers this option.defaultWithAlign will now also align %%%.newlines.alwaysBeforeCurlyBraceLambdaParams.align.tokens can now align on tokens that have no leading space.
For example, with settings align.tokens = [ ":" ]
// Before
def foo(
a: Int,
aa: Int
)
// After
def foo(
a: Int,
aa: Int
)
NOTE. This may play badly in combination with other alignment configuration.
For example, if you configure to align extends and :,
the following input will align neither since the rows don't match
case object A extends Super
case class B(b: B) extends Super
*.sbt files of your build by default.
To disable, configure in your build.sbt (note, not .scalafmt):
formatSbtFiles in ThisBuild := false..scalafmt configuration.--poorMansTrailingCommasInConfigStyle <bool>.
For context, see SIP-27.
// false (default)
function(
a,
b,
c
)
// true
function(
a
, b
, c
)
*.sbt file and it should just work automatically.
Set --formatSbtFiles false to disable this.// 1. Indentation for orphan parentheses is no longer 4 spaces.
// Before
assert((p1 match {
case Param.Configured(x) => x()
case x => throw new MatchError(x)
}) == failureAccrualPolicy)
// 0.3.0
assert((p1 match {
case Param.Configured(x) => x()
case x => throw new MatchError(x)
}) == failureAccrualPolicy)
// 2. Line breaks in nested scopes are more heavily penalized.
// Before
system.actorOf(Props[ThreadNameEcho].withDispatcher(
"myapp.balancing-dispatcher")) ! "what's the name?"
// 0.3.0
system.actorOf(
Props[ThreadNameEcho]
.withDispatcher("myapp.balancing-dispatcher")) ! "what's the name?"
Please open an issue if you prefer the previous output. In some cases
the new rules may result in worse formatting output but after looking
through thousands of lines of diffs I think the new rules provide a more
consistent, readable and compact output than before.--continuationIndentCallSite is now 2 spaces
instead of 4 spaces.
Why? Because it's consistent with many popular coding styles and it
saves a lot of horizontal space for deeply nested code.
--continuationIndentDefnSite is still 4 spaces to prevent
method bodies from aligning with parameter lists:
def foo(
a: Int): Int = {
a + 1
}--alignByArrowEnumeratorGenerator is now false
instead of true. Refer to align.arrowEnumeratorGenerator.// before
ClusterSharding(system).start(
className[Flow], {
case (name: String, payload) => (name, payload)
}, {
case (name: String, _) => (name.hashCode % shardCount).toString
}
)
// 0.3.0
ClusterSharding(system).start(
className[Flow],
{ case (name: String, payload) => (name, payload) },
{ case (name: String, _) => (name.hashCode % shardCount).toString }
)--assumeStandardLibraryStripMargin true now aligns by a pipe
character on the first line if there is one. See #324.
// before
"""|first
|second""".stripMargin
// 0.3.0
"""|first
|second""".stripMargin--style IntelliJ that aims to mimic the default
formatting settings of IntelliJ.--alignMixedOwners <bool> to allow vertical alignment
across val/var/def and object/trait/class. Enabled by default in
defaultWithAlign. See #184.--binPackImportSelectors <bool> to decide how to format
long import selector lines. See #101.
// before
import org.scalajs.dom.experimental.serviceworkers.{ServiceWorkerGlobalScope, ServiceWorkerRegistration, A}
// 0.3.0 --binPackImportSelectors false (default)
import org.scalajs.dom.experimental.serviceworkers.{
ServiceWorkerGlobalScope,
ServiceWorkerRegistration,
A
}
// 0.3.0 --binPackImportSelectors true
import org.scalajs.dom.experimental.serviceworkers.{
ServiceWorkerGlobalScope, ServiceWorkerRegistration,
A
}= in vals and vars
are now preserved. See #356.
// If you force a line break after = like this
val x: Int =
2
// then scalafmt will keep the line break. Before scalafmt
// would move the whole statement into a single line.// before
implicit def adtSyntax[A](target: A): Any = macro LiftMacros
.materializeADTSyntax[A]
// 0.3.0
implicit def adtSyntax[A](target: A): Any =
macro LiftMacros.materializeADTSyntax[A]--indentOperators <bool>
// true (default)
def routes = {
pathPrefix("foo") {
???
} ~
pathPrefix("bar") {
???
}
}
// false (pre 0.2.10 behavior)
def routes = {
pathPrefix("foo") {
???
} ~
pathPrefix("bar") {
???
}
}--indentOperatorsIncludeFilter <str>.
See docstring.--indentOperatorsExcludeFilter <str>
See docstring.FormatResult.Incomplete is now
a FormatResult.Failure(e: Incomplete).reformatDocstrings in favor of reformatCommentsalignStripMarginStrings in favor of assumeStandardLibraryStripMargin--spaceBeforeContextBoundColon flag.
// false (default)
def f[T: Numeric](t: T) = ???
// true
def f[T : Numeric](t: T) = ???
// 0.2.10
{
buf +=
sh"${foo} aa"
}
// 0.2.11
{
buf +=
sh"${foo} aa"
}
--danglingParentheses true
Fixes single issue reported in #325.
// 0.2.9
Props(
new Actor {
context.stop(self)
override def receive = Actor.emptyBehavior
}
)
// 0.2.10
Props(new Actor {
context.stop(self)
def receive = Actor.emptyBehavior
})--reformatDocstrings false to disable docstring
reformatting (on by default).--bestEffortInDeeplyNestedCode (off by default) to
reenable best-effort formatting as was default prior to 0.2.6.
If you get a lot of "Search state exploded" errors in IntelliJ,
you might want to try this out.
The setting was disabled in 0.2.6 because it sometimes produces bad
output.--danglingParentheses. I imagine we
will soon officially support a style with these settings
--continuationIndentCallSite 2
--danglingParentheses true
--alignByOpenParenCallSite false
--maxColumn 100
Give it a try see if you like it.
It's somewhat inspired by IntelliJ's default formatting settings.
I don't know yet what to call the style.
Thanks @lihaoyi for helping out.+ - / += >>= ^^ || &&
are preserved from the original input, even if that means the output
breaks the --maxColumn limit. Why? Because infix operators are
heavily used in DSLs, which often use special formatting layouts to
express ideas. Instead of ruining the hard-earned formatting layout
in the original source, I prefer to keep it until scalafmt becomes smarter.
In future releases, I would like to add support to format at least the most
common operators like + && || -.function(
argument1, argument2)
has been removed in favor of either of these
function(argument1,
argument2)
// OR
function(
argument1,
argument2)--alignByOpenParenCallSite false to disable the following
formatting layout for argument lists.
function(argument1,
argument2)
Tuples will still be aligned by the opening parenthesis.--danglingParentheses true for users who want dangling
parentheses. This comes at the price of not being able to
force "config-style" arguments. I highly recommend you set
--alignByOpenParenCallSite false in combination with this flag.
Note that this flag is quite different from the Scalariform dangling
parenthesis option.--rewriteTokens from1;to1,from2;to2,... to rewrite
arbitrary tokens into other tokens. For example,
rewrite.tokens = ["⇒;=>,←;<- will rewrite unicode arrows to their
ascii equivalents. Flip the tokens to get the opposite behavior.spaces.afterTripleEquals = false to get spaces after
triple equals in cases like this
x should === (y)$HOME/.scalafmt
if there is no .scalafmt in a project's root directory.
See #239.
with if a class/trait/object
definition doesn't fit in a single line. Set --binPackParentConstructors true
to get the old behavior where scalafmt would fit as many parent constructors
on a line as possible.unmanagedSourceDirectories instead of
scalaSource to decide which files to format.
This should improve your experience in Scala.js and cross-built projects.stripMargin comes from the standard library (discussion here #170).
Refer to assumeStandardLibraryStripMargin to enable it at your own risk..scalafmt changes.
Instead, new changes are picked up automatically and a green info bubble
pops up.NOTE. This release contains a bug, see #192. Please hold off from upgrading.
This release changes the formatting rules for many small cases. I recommend you reformat your whole project in one commit.
--spacesInImportCurlyBraces flag.
defaultWithAlign will not jump scope #152.defaultWithAlign now includes a lot more alignment rules,
see the diff against 0.2.0.
and updated test suite.--alignTokens please try again,
it may have been caused by #151..scalafmt now supports comments starting with #.ScalaFmt was renamed to Scalafmt.scalafmtFormat sbt task is now scalafmt.ScalaStyle is now ScalafmtConfig.ScalaFmt.format and
ScalaFmt.format_! have been replaced by a single
Scalafmt.format. The new methods supports more flexibility
via the ScalafmtRunner
argument.| computer | 75th percentile | average | max |
|---|---|---|---|
| 2.5 ghz i7 macbook pro | 119ms | 112ms | 7.1s |
| travis ci (for fun) | 3.7s | 2.8s | 45.2s |
there is still a lot of work to do. the plan is to investigate the 90+ percentile cases in future releases as well as run more jmh benchmarks.
object forloopguards {
for {
x <- list(1, 2, 3)
if (x != 1)
if (x != 3)
} yield x
}
new foo with bar with kaz {}// column |
// before
List(1)
.map { x =>
x + 1
}
// after
List(1).map { x =>
x + 1
}// stay at indentation 0).-f flag in the CLI can be a directory.
This page was last updated on Jun 11, 2018.