treefmt-nix — treefmt configuration for nix users
This repo is for developers that use both nix and
treefmt. Treefmt is a tool that helps you format all your project with one command, and nix is a package manager that allows you to specify build configurations in a functional manner.
Things work differently with nix than with other package managers. This is why it's handy to have a tool that helps you specify treefmt build options, dependencies and config in one place.
With treefmt-nix, you don't have to install neither the formatters nor treefmt manually. treefmt-nix installs and configures the needed formatters for you. It maps formatting programs to treefmt.toml entries -- pre-crafted formatter-configs maintained by the community.
Basically, these configs are the most valuable part of this repository. They are located in the programs folder of this project.
Usage
Nix classic
To run treefmt-nix with nix-classic, import the repo using niv:
$ niv add numtide/treefmt-nix
Alternatively, you can download the source and run nix-build in the project root directory:
$ nix-build
The command will return the helper functions which will be later used to produce a derivation from the specified treefmt-nix configuration.
After you installed treefmt-nix, specify the formatter configuration. For instance, this one is for formatting terraform files:
# myfile.nix
{ system ? builtins.currentSystem }:
let
nixpkgsSrc = builtins.fetchTarball "https://github.com/NixOS/nixpkgs/archive/refs/heads/nixos-unstable.tar.gz";
treefmt-nixSrc = builtins.fetchTarball "https://github.com/numtide/treefmt-nix/archive/refs/heads/master.tar.gz";
nixpkgs = import nixpkgsSrc { inherit system; };
treefmt-nix = import treefmt-nixSrc;
in
treefmt-nix.mkWrapper nixpkgs {
# Used to find the project root
projectRootFile = ".git/config";
# Enable the terraform formatter
programs.terraform.enable = true;
# Override the default package
programs.terraform.package = nixpkgs.terraform_1;
# Override the default settings generated by the above option
settings.formatter.terraform.excludes = [ "hello.tf" ];
}It's a good practice to place the configuration file in the project root directory.
Next, execute this command:
$ nix-build myfile.nix
This command returns a derivation that contains a treefmt binary at ./result/bin/treefmt in your current directory. The file is actually a symlink to the artifact in /nix/store.
treefmt.toml in this case isn't generated: the binary is wrapped with the config.
Flakes
Running treefmt-nix with flakes isn't hard. The library is exposed as the lib attribute:
# flake.nix
{
inputs.treefmt-nix.url = "github:numtide/treefmt-nix";
outputs = { self, nixpkgs, systems, treefmt-nix }:
let
# Small tool to iterate over each systems
eachSystem = f: nixpkgs.lib.genAttrs (import systems) (system: f nixpkgs.legacyPackages.${system});
# Eval the treefmt modules from ./treefmt.nix
treefmtEval = eachSystem (pkgs: treefmt-nix.lib.evalModule pkgs ./treefmt.nix);
in
{
# for `nix fmt`
formatter = eachSystem (pkgs: treefmtEval.${pkgs.sytem}.config.build.wrapper);
# for `nix flake check`
checks = eachSystem (pkgs: {
formatting = treefmtEval.${pkgs.sytem}.config.build.check self;
});
};
}And also add the treefmt.nix file (or put the content inline if you prefer):
# treefmt.nix
{ pkgs, ... }:
{
# Used to find the project root
projectRootFile = "flake.nix";
# Enable the terraform formatter
programs.terraform.enable = true;
# Override the default package
programs.terraform.package = pkgs.terraform_1;
# Override the default settings generated by the above option
settings.formatter.terraform.excludes = [ "hello.tf" ];
}This file is also the place to define all the treefmt parameters like includes, excludes and formatter options.
After specifying the flake, run nix fmt:
$ nix fmt
Nix-fmt is a tool to format all nix files in the project, but with the specified flake, it starts treefmt-nix and formats your project.
You can also run nix flake check (eg: in CI) to validate that the project's
code is properly formatted.
Flake-parts
This flake exposes a flake-parts module as well. To use it:
-
Add
inputs.treefmt-nix.flakeModuleto theimportslist of yourflake-partscall. -
Add
treefmt = { .. }(containing the configuration above) to yourperSystem. -
Add
config.treefmt.build.wrapperto thenativeBuildInputsof yourdevShell. This will make thetreefmtcommand available in the shell using the specified configuration.You can also use
config.treefmt.build.programsto get access to the individual programs, which could be useful to provide them to your IDE or editor.For an example, see haskell-template's
flake.nix.
See this page for details.
Configuration
While dealing with treefmt outside of nix, the formatter configuration is specified in a toml format. On the contrary, with nix, you write in with a nix syntax like this:
# Used to find the project root
projectRootFile = ".git/config";
# Enable the terraform formatter
programs.terraform.enable = true;
# Override the default package
programs.terraform.package = nixpkgs.terraform_1;
# Override the default settings generated by the above option
settings.formatter.terraform.excludes = [ "hello.tf" ];Options:
Project root fileis the git file of the project which you plan to format.- The option
programs.terraform.enableenables the needed formatter. You can specify as many formatter as you want. For instance:
programs.terraform.enable = true;
programs.gofmt.enable = true;
- The option
programs.terraform.packageallows you to use a particular build/version of the specified formatter. - By setting
settings.formatter.terraform.excludesyou can mark the files which should be excluded from formatting. You can also specify other formatter options or includes this way.
For detailed description of the options, refer to the treefmt documentation.
Project structure
This repo contains a top-level default.nix that returns the library helper functions.
mkWrapperis the main function which wraps treefmt with the needed configuration.mkConfigFileevalModuleall-modules
Supported programs
treefmt-nix currently supports the following formatters:
- alejandra
- beautysh
- black
- buildifier
- cabal-fmt
- clang-format
- cue
- deadnix
- dhall
- dprint
- elm-format
- erlfmt
- fnlfmt
- gofmt
- gofumpt
- google-java-format
- hclfmt
- hlint
- isort
- mdformat
- mdsh
- nixfmt
- nixpkgs-fmt
- ocamlformat
- ormolu
- prettier
- purs-tidy
- ruff
- rufo
- rustfmt
- scalafmt
- shellcheck
- shfmt
- stylish-haskell
- stylua
- taplo
- terraform
- yamlfmt
- zprint
For non-Nix users, you can also find the generated examples in the
./examples
folder.
Adding new formatters
To add a new formatter, look in the programs folder to see how the files there are structured.
We happily accept new PRs as long as they adhere to the formatter
specifications. In terms of default configurations, we don't try to be edgy. Please pick defaults that are standard in your community -- for instance, python is usually indented with 4 spaces, so don't add a python formatter with 2 spaces as the default.
License
All the code and documentation is licensed with the MIT license.