NumTide

DevOps consulting by Developers.

Nixpkgs-fmt: Road to Everybody Nixpkgs Formatter

Andika Demas Riyandi

2020-09-02

TL;DR; we are excited to release the nixpkgs-fmt (a Nix Language code formatter) version v1.0.0 for everyone to try. There are a couple of changes to the latest edition that you need to pay attention to before using nixpkgs-fmt such as indentation, newline, antiquotation, and multiline-string. Thus, we really encourage you as a nix user to try nixpkgs-fmt for all of your nix projects so we can improve it.

Historical background

A people without the knowledge of their past history, origin and culture is like a tree without roots. -- Marcus Garvey

Before we jump into the technical aspect of nixpkgs-fmt, I would like to share the background story on why we decided to create this project in the first place. It began with this discourse post made by zimbatm about the need of a universal code formatter for our lovely Nix code, and at that time, the reasons to have such formatter are: (1) code readability, (2) editor-friendly, and (3) easy to use copy-and-paste between nix code.

In that post, there are also some initial goals that should be achieved by this new formatter (which is later named nixpkgs-fmt), which are:

  1. Have a stable formatter, meaning that running it twice should give the same output;
  2. The formatter should be a single binary that can be copied around;
  3. Implement (or re-use) a comment-preserving Nix parser in the language of your choice.

NumTide first hired matklad from Ferrous Systems to implement the first iteration of the project. Matklad is also the author of rowan, the underlying parsing rust library. The project beta announcement happened in August 2019, and the first version released since the announcement was version 0.3.1. By the time, another project called nix-fmt was released, which prompted us to rename the project to nixpkgs-fmt.

After the beta announcement, the development of nixpkgs-fmt continues to happen and NumTide continues sponsoring the project. Luckily, I was hired to work on the formatter in February 2020 and have been since then.

About the Project

Similar to all the languages in the universe, Nix needs a code formatter. With that in mind, nixpkgs-fmt is the one made for it. If you want to know more about Nix, please go to nix official page. Moreover, as mentioned in the previous historical background section, nixpkgs-fmt's main goal is to provide some overall consistency in the nix code submitted to nixpkgs, NixOS' main package repository. In that case, its final goal is to be a standard formatter for the nixpkgs repository so that every pull-request is formatted uniformly.

The difference between nixpkgs-fmt and other nix formatters out there is how it formats the code. nixpkgs-fmt does not pretty-print the code, but it uses specific rules for spacing and indentation so that the result will be closely similar to the existing what most nix code written in nixpkgs repository. And thanks to matklad for his library rowan, and jD91mZM2 for rnix-parser, the formatting engine and rules of nixpkgs-fmt can be implemented easily.

Therefore, we hope that the release stable version of v1.0.0 announced in this article can also attract more nix user to use and integrate nixpkgs-fmt to their existing project. This is very important to the continuation of nixpks-fmt development.

v1.0.0 Changes

After reaching version 1.0.0, there are several changes that should be noted by the developer in order to gain maximum usability of nixpkgs-fmt in their projects:

  1. nixpkgs-fmt is able to format up to the part of code that is missing or broken. So, whenever you see the wrong indentation or code structure, your first guess should be syntax error exists in your codebase.

  2. nixpkgs-fmt handles multi-line string code with a different approach. It formats the code line by line similar to the other, but with a different calculation for indentation. It does not have an indentation rule for multi-line string and therefore, you should pay attention to your code indentation inside a multi-line string.

How to use nixpkgs-fmt

By the time this post is written, the only guide you have to use nixpkgs-fmt is explained in the project's readme. It is still under development, so any suggestions or questions are really appreciated. We are going to take some information from the readme and add some additional information that we think will help you setup nixpkgs-fmt in your project smoothly. There are multiple ways to install nixpkgs-fmt into your system, but we only cover for NixOS in this post.

Using nix-env

Since nixpkgs-fmt is already in nixpkgs' master, you can install it directly by using nix-env -i nixpkgs-fmt or through nix-env -f https://github.com/nix-community/nixpkgs-fmt/archive/nixpkgs-unstable.tar.gz -i if you want to install it directly from nixpkgs-fmt repository.

Pre-commit hook

Pre-commit is a framework that can hooks on every commit to automatically point out issues in code such as missing semicolons, trailing whitespace, and debug statements. That is when nixpkgs-fmt fits really well.

To add nixpkgs-fmt as a pre-commit hook in your project, you need to add it to your project's .pre-commit-config.yaml (you need to have rust in your environment variable):

-   repo: https://github.com/nix-community/nixpkgs-fmt
    rev: master
    hooks:
    -   id: nixpkgs-fmt

Since we also use nixpkgs-fmt in our main repository, you can take a look at how we implement it into its own repository.

Call to Action

We would like to invite you as nix developer to test nixpkgs-fmt. If you want to play around with the formatter, you can go to our demo website. We also need more use cases and suggestions to improve nixpkgs-fmt in the future, so if you notice some weird behavior in nixpkgs-fmt please do not hesitate to open an issue.