Improving Scalariform, the Scala Source Formatter

Scalariform is a Scala source code formatter, originally written by Matt Russell (big thanks to him for writing it).

It’s much easier to show you what this does than it is to try and explain it, so that’s what I’ll do.

This is some poorly formatted code before running Scalariform:

1
2
3
4
5
6
7
8
9
10
11
class Coffee {
val sugarCubes = 20
val isCaffeinated = false

def energyBoost = {
if (caffeinated)
100 * sugarCubes
else
0
}
}

After running Scalariform:

1
2
3
4
5
6
7
8
9
10
11
class Coffee {
  val sugarCubes = 20
  val isCaffeinated = false

  def energyBoost = {
    if (caffeinated)
      100 * sugarCubes
    else
      0
  }
}

Pretty cool, right? Unfortunately, there haven’t been very many updates to the official version of this super awesome project lately, so I decided to fork the project and start improving upon it myself. Since I use Scala quite often, I’ve got some pretty strong motivation to work on improving it.

Here’s a quick summary of what I’ve added to Scalariform so far:

Previous Scalariform Formatting
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
def showInput[A](
  parent: Component = null,
  message: Any,
  title: String = uiString("OptionPane.inputDialogTitle"),
  messageType: Message.Value = Message.Question,
  icon: Icon = EmptyIcon,
  entries: Seq[A] = Nil,
  initial: A
): Option[A]

case class Cake(
  icingFlavor: Flavor = Vanilla,
  cakeFlavor: Flavor = Chocolate,

  candles: Int = 1,
  layers: Int = 3,
  iceCream: Boolean = False
)

o.manyArguments(abc = 0,
  abcOne = 1,
  abcTwo,
  abcThree = 3,
  abcFour = 4,
  abcFive = 3
)
Scalariform Formatting with My Changes
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// Parameter names, types, and defaults are aligned into three separate columns
def showInput[A](
  parent:      Component     = null,
  message:     Any,
  title:       String        = uiString("OptionPane.inputDialogTitle"),
  messageType: Message.Value = Message.Question,
  icon:        Icon          = EmptyIcon,
  entries:     Seq[A]        = Nil,
  initial:     A
): Option[A]

// Two newlines will result in separate alignment groups 
case class Cake(
  icingFlavor: Flavor = Vanilla,
  cakeFlavor:  Flavor = Chocolate,

  candles:  Int     = 1,
  layers:   Int     = 3,
  iceCream: Boolean = False
)

// Same feature working with method calls
o.manyArguments(
  abc    = 0,
  abcOne = 1,
  abcTwo,
  abcThree = 3,
  abcFour  = 4,
  abcFive  = 3
)

And here’s how to use my version:

Scalariform Formatting with My Changes
1
2
3
4
// Add this to .../project/plugins.sbt
resolvers += "Sonatype OSS Snapshots" at "https://oss.sonatype.org/content/repositories/snapshots"

addSbtPlugin("com.danieltrinh" % "sbt-scalariform" % "1.3.0-SNAPSHOT")

See the plugin for how to configure formatting options, and the Scalariform readme for available formatting options.

Since this is an ongoing project, there will be more updates to come.