Can't someone else do it?


An automatic formatting tool is better than quibbling at formatting issues in pull requests. Why paying attention to something that can be automatically minded for? Can’t someone else do it? That’s the reason we use scalafmt where I work.

Homer Simpson touting: 'Can't SOMEONE else DO it?'

Why formatting the code yourself when someone else can do it (automatically)?

Now IntelliJ has direct support for scalafmt, not so long ago I needed to use a separate plugin for that. But there is a small problem. There are small corner cases in which the IDE-triggered reformat doesn’t reformat stuff than the SBT-triggered one would do. Therefore, from time to time, the Jenkins build complains about my pull requests for having files incorrectly formatted…

Not anymore!

Let’s remove the frustration of needed to wait again for the Jenkins build from time to time! (This instructions are tailored for OS X, feel free to replace brew with apt-get or equivalent for your system).

First, we are installing nailgun, a protocol and server that solves the problem of long initialization times for JVM executables. With nailgun you have a background JVM process that is already started and ready to execute scalafmt or any other program with nailgun support.

$ brew install nailgun

Then, we are installing scalafmt standalone with nailgun support so that we can reformat or check formatting from other scripts:

$ sudo coursier bootstrap --standalone org.scalameta:scalafmt-cli_2.12:2.0.1 \
  -r sonatype:snapshots \
  -o /usr/local/bin/scalafmt_ng -f --main com.martiansoftware.nailgun.NGServer

To guarantee that the server is always running whenever we login we can use a launchd agent (launchd is the evolution and replacement of initd in the Darwin family of Unix). To do so, we should create ~/Library/LaunchAgents/scalafmt_ng.plist with this contents:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" 
          "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>KeepAlive</key>
  <true/>
  <key>Label</key>
  <string>scalafmt_ng</string>
  <key>ProgramArguments</key>
  <array>
    <string>/usr/local/bin/scalafmt_ng</string>
  </array>
  <key>RunAtLoad</key>
  <true/>
</dict>
</plist>

If we restart our session or run launchctl load scalafmt_ng.plist the nailgun server will be ready for service.

Finally, we can write a git hook to check that our files are properly formatted:

#!/bin/sh
set -e
# Check but don't reformat sources with scalafmt
ng org.scalafmt.cli.Cli \
    --non-interactive --quiet \
    --git true \
    --test \
    -c .scalafmt.conf \
    --exclude target \
    `find . -iname scala -type d | grep -v target | grep -v bloop`

I have this file at ~/.githooks/scalafmt-check to avoid duplication. To enable these checks for a repo I simply link it to the pre-commit and pre-push hooks:

$ cd repo
$ ln -s ~/.githooks/scalafmt-check .git/hooks/pre-commit
$ ln -s ~/.githooks/scalafmt-check .git/hooks/pre-push

Now we can instantly know whether we are trying to commit/push code that is not well formatted:

$ git commit -a -m"Test commit"
Looking for unformatted files...
All files are formatted with scalafmt :)

If you prefer to reformat on commit you can go with almost the same script excluding the --test flag.

The moral of the story

Remove frustration and friction from your daily life. You’ll be happier and more productive!