q-analog

Two things really annoyed me about clang-format. First, that it formats even the lines that I didn't change, so now the reviewer has to wade through noise. Second, that it doesn't abide by the principle of trying to maintain the existing code style in a file, even if the local code style contradicts with the global style.

It turns out it's pretty easy to have clang-format only touch the lines you've changed. clang-format includes a script for this that parses diffs, called clang-format-diff.py, but it's not installed to my PATH by Homebrew so I just downloaded it:

brew install clang-format
curl -O https://raw.githubusercontent.com/llvm-mirror/clang/master/tools/clang-format/clang-format-diff.py

Now you can easily format the changes in git diff:

git diff -U0 --no-color HEAD^ | python clang-format-diff.py -p1 -i

I've put the last command in a script called git-fmt, so I can just run git fmt in a Git repository to format my current changes (git x calls git-x if it's in your PATH).

I don't have a perfect solution for the second problem. But clang-format does have a nice configuration option called DerivePointerAlignment. This means it'll decide whether to write T *x vs. T* x based on what's most common in the file that's being modified. Here's the .clang-format for an Objective-C++ project I'm working on whose code style is inconsistent between files:

---
BasedOnStyle: LLVM
IndentWidth: 4
BreakBeforeBraces: Allman
ColumnLimit: 100
DerivePointerAlignment: true
PointerAlignment: Right
---

Configuration options are listed here.

These two things mean I'm now a lot less annoyed by clang-format than I used to be, to the point where I now run git fmt pretty often just to avoid having to worry about indentation and style myself.

Enter your email to subscribe to updates.