May 12, 2019·5 min read·engineeringnixformattingtooling

nixfmt publishes an alpha for consistent Nix formatting

Serokell's nixfmt alpha separates parsing from width-aware pretty printing. Its announcement distinguishes the ability to process Nixpkgs from agreement on a final formatting style.

A formatter can process a large codebase before its authors are satisfied with the layout it produces. That is the position of the nixfmt alpha announced by Serokell on May 12. The announcement says the tool parses and formats all of Nixpkgs, while acknowledging unattractive results in some cases. It presents consistent formatting as available work and a broadly accepted style as work still ahead.

That distinction is useful for Nix. The language needs tools that can handle real expressions, but successfully parsing those expressions does not settle how they should look. A formatter has to preserve the relationships in the source and choose a readable arrangement for them. Those are related requirements with different evidence.

The declarative system model is what attracts me to Nix, and source readability matters to that model. A configuration becomes harder to review when its layout obscures which expression supplies a value. Consistent formatting can remove incidental variation while still leaving the reviewer responsible for understanding the declaration.

Parsing precedes layout

The formatting entry point at the announcement revision gives a concise view of the mechanism. The format function accepts a width, a filename and input text. Its result is either a parse error bundle or formatted text.

The implementation first invokes the parser's file rule. Only a successful parse proceeds to layout at the selected width. That sequencing matters because the tool is not merely changing spaces according to nearby characters. It builds an internal representation before deciding how to print it.

The announcement identifies Megaparsec and text as libraries used in the implementation. It also describes a custom pretty printer originally based on prettyprinter. The separation visible in the entry point matches that account. Parsing determines the structure that the printing stage then arranges.

A width parameter is a layout input. It does not change what a Nix expression is intended to mean. The formatter uses it to choose output text, while the parser remains responsible for whether the input can be represented as a valid file under its rules.

The alpha already has two operating modes

The README published with the alpha describes a standard-input mode and an in-place mode. Feeding text on standard input prints the formatted result on standard output. Naming a file formats that file in place.

The stream form makes the data flow explicit.

nixfmt < input.nix > formatted.nix

The input and output names in this example are different. It adapts the documented standard-input mode so the produced text has its own destination. It does not imply that the alpha compares the two files or verifies semantic equivalence after printing.

The announcement also gives a width option, using -w80 with named input files after building the project. That establishes a concrete control over layout. It does not imply that the tool supports an extensive set of style preferences, because the announcement does not describe such a configuration system.

The period README warns that the tool remains a work in progress and that its in-place mode can cause data loss. That is an explicit limitation stated by the authors. The stream mode is therefore a meaningful part of the initial interface, allowing the formatted text to be inspected separately from the original.

Repository coverage and style quality differ

Serokell reports formatting all of Nixpkgs in about 20 seconds on a dual-core CPU, and individual files such as all-packages.nix in less than a second. Those are the authors' reported measurements. They describe the alpha's observed processing time under the conditions they name, not a timing guarantee for every machine.

The more important scope claim is that the tool can parse and format the repository. A parser that works only on a small set of examples would leave a large integration gap. Exercising the package collection gives the authors a wider body of actual source against which to discover failures.

It still does not prove that every emitted layout is desirable. The announcement itself makes that qualification. Its authors want to improve the output before calling the tool widely usable, then work with the community toward an officially accepted formatter.

That sequence gives each claim an appropriate status. The alpha exists under the MPL 2.0 license. The stated coverage and timing are current reports. A finished style and official acceptance remain goals. Reading the announcement as though all those stages have already happened would erase the reason it is called an alpha.

Continuation indentation is an immediate design question

The same day's discussion provides a concrete example of a formatting objection. A user points to a list expression continued through a call to lib.optionals and asks whether continuation lines can receive more indentation. The concern is that a partial statement at the surrounding indentation level is difficult to read.

That is a useful kind of feedback because it names the relationship the layout is failing to communicate. The issue is not merely a preference for more spaces everywhere. The continuation belongs to an expression already started, and the reader wants its visual position to express that dependence.

The example also shows why consistency alone is insufficient. A formatter can apply the same rule repeatedly and still make an important syntactic relationship hard to see. Improving that rule requires deciding what information the layout should convey across different expression shapes.

My preference is to judge that choice by how readily the configuration can be reviewed. Uniform output helps when it removes unrelated layout decisions from a change. It helps less when the reader must reconstruct a continuation that the formatter has aligned ambiguously.

Community agreement remains a separate result

The authors invite contributions and provide a deployed demonstration. That makes the alpha a concrete basis for discussion instead of an abstract argument about a preferred Nix style. Users can point to the output produced for an actual expression.

The available implementation already defines a useful boundary between parsing failures and layout decisions. A rejected file requires work on syntax handling. A parsed file with an awkward continuation requires work on printing. Keeping those cases separate gives contributors a clearer way to describe what needs to change before the formatter reaches its stated usability goal.