cformat

A program to incrementally reformat changed files using clang-format(1).


Keywords
diff, utility, cli, text, git
License
CNRI-Python-GPL-Compatible

Documentation

cformat

Purpose

cformat is a program for conveniently formatting changes made to C or C++ files using clang-format. Contrary to most formatters, the program allows for incremental reformatting of files. That is, when lines in a file are changed they and only they will be reformatted (optionally with some context), while the remainder of the file will be preserved as-is. Such behavior can be tremendously useful in incrementally migrating over a code base to being formatted in an automated fashion.

Given that the program is merely a wrapper around clang-format, it automatically picks up the corresponding configuration.

Usage

cformat interprets a patch in unified diff format and infers files and changed lines based on it. This patch is read from standard input.

While not at all tied to git, we use it here for illustration purposes (and because it is likely the context in which the program will be used). To simplify usage, we introduce a git alias (git cfp -- "c format patch") that retrieves any currently staged changes and pipes them to the program. An alias for annotating the currently staged changes could look like this:

[alias]
  cfp = "!cfp() { git diff --no-prefix --relative --staged --unified=0 \"$@\" | cformat; }; cfp"

Once you have staged changes, you can run git cfp and affected lines will get reformatted according to clang-format's rules.

Three aspects of the above definition are of particular relevance here:

  • --no-prefix is important to make sure that paths contained in emitted diffs do not contain any a/ prefixes but map right to files in the file system
  • --relative is necessary because without it git emits file names relative to the repository root, whereas cformat may be invoked from a sub-directory, in which case paths would not necessarily map to files
  • --unified=0 ensures that only lines that were actually touched are reformatted, as opposed to lines contained in the context that is used for fuzzy matching; increase the context to format additional lines surrounding changes

Installation

cformat is written in Rust and requires the Cargo package manager to be built. It can be installed using cargo install cformat. It relies on clang-format being installed and runnable.