clang-format is a tool that can format source code of C-like languages (C /
but it is also possible to fine tune its behavior with a configuration file
.clang-format. It has quite a lot
First of all, you need to have the
clang-format program somewhere in your
PATH. You can get it here. For
Windows, there is a
bundle containing various
tools. Just unzip it with 7zip and keep only the
Next, you’ll need to define your style preferences. Mine currently look like this:
BasedOnStyle: LLVM AccessModifierOffset: -4 AlignConsecutiveAssignments: true AlignConsecutiveDeclarations: false AlignOperands: true AlignTrailingComments: true AllowAllParametersOfDeclarationOnNextLine: false AllowShortBlocksOnASingleLine: false AllowShortCaseLabelsOnASingleLine: false AllowShortFunctionsOnASingleLine: None AllowShortIfStatementsOnASingleLine: false AllowShortLoopsOnASingleLine: false BinPackArguments: false BinPackParameters: false BreakAfterJavaFieldAnnotations: true BreakBeforeBinaryOperators: NonAssignment BreakBeforeBraces: Attach ColumnLimit: 120 ContinuationIndentWidth: 4 IndentCaseLabels: true IndentWidth: 4 SortIncludes: false SpaceAfterCStyleCast: true TabWidth: 4 UseTab: Never
You can start with a preset and play with it until it is what you like.
In order to find the style options, clang-format searches for a file called
.clang-format at the current directory. When it can’t find it, it continues
the search recursively to parent directories. This means that if you keep your
git repositories under a common folder, you can store the
at the root. And if a project needs different settings, you can always override.
At this point you can experiment with
clang-format from the command line to
see how it works. There are also plugins for IDEs that use it.
Now, the fun part. We’ll setup a git repository to automatically format Java
files with clang-format. You need a
.gitattributes file on your repository
(see documentation). There, you
specify that java files will go through the
Note that git doesn’t know anything about this, so we need to define what that filter does. Run the following commands:
git config --global filter.clang-format-java.clean 'clang-format -assume-filename=test.java' git config --global filter.clang-format-java.smudge cat
A filter has two operations, clean and smudge. Clean happens when files are staged, smudge when files are checked out.
When files are staged, we run
clang-format -assume-filename=test.java. The
-assume-filename parameter helps clang-format to understand we’re formatting a
Java file. This is needed because the input is received from the stdin and there
is no filename information available.
The effect is that when we’re staging files (e.g. with
git add) what is staged
goes first through clang-format and gets “cleaned” (hence the name of the clean
The smudge operation
cat simply outputs the clean file as-is.
Note that the
.gitattributes file is part of the git repository, while the
filter definition is part of the git configuration. If someone uses the
repository without having configured the filter, git will not give an error.
It’s a good idea to add the commands that setup the filters in a readme or as
comments in the
.gitattributes file, e.g.:
# To enable the custom clang-format-java filter, you need to run: # git config --global filter.clang-format-java.clean 'clang-format -assume-filename=test.java' # git config --global filter.clang-format-java.smudge cat *.java filter=clang-format-java