treefmt-nix

repository·main·Indexed 20 days ago

https://github.com/numtide/treefmt-nix

A Nix library for managing multi-language file formatting using treefmt. It integrates with the Nix ecosystem, providing wrapped binaries for use with `nix fmt` and CI checks. It supports over 100 formatters and provides tools like `mkWrapper` for Nix classic and `evalModule` for Nix Flakes and flake-parts.

Tokens
2K
Snippets
4
Records
10
Agent score
21%

What's inside treefmt-nix

  1. Integrate treefmt-nix with Nix Flakes

    main

    To use treefmt-nix with Flakes, import the library via inputs.treefmt-nix.url = "github:numtide/treefmt-nix".

    You can use treefmt-nix.lib.evalModule to evaluate your configuration (defined in a treefmt.nix file) across multiple systems. This allows you to export a formatter for use with nix fmt and checks for use with nix flake check in CI.

    1. Define your configuration in treefmt.nix.
    2. Use evalModule in your flake.nix to generate the system-specific configurations.
    3. Run nix fmt to format your project using the wrapped treefmt binary.
    # flake.nix
    {
      inputs.treefmt-nix.url = "github:numtide/treefmt-nix";
      inputs.systems.url = "github:nix-systems/default";
    
      outputs = { self, nixpkgs, systems, treefmt-nix }: 
        let
          eachSystem = f: nixpkgs.lib.genAttrs (import systems) (system: f nixpkgs.legacyPackages.${system});
          treefmtEval = eachSystem (pkgs: treefmt-nix.lib.evalModule pkgs ./treefmt.nix);
        in
        {
          # for `nix fmt`
          formatter = eachSystem (pkgs: treefmtEval.${pkgs.system}.config.build.wrapper);
          # for `nix flake check`
          checks = eachSystem (pkgs: {
            formatting = treefmtEval.${pkgs.system}.config.build.check self;
          });
        };
  2. Install treefmt-nix with Nix classic

    main

    To use treefmt-nix in a non-flake Nix environment, you can use niv to add the repository:

    $ niv add numtide/treefmt-nix

    Alternatively, you can download the source and run nix-build in the project root directory to obtain the helper functions.

  3. Configure treefmt-nix using mkWrapper (Nix classic)

    main

    In Nix classic, use the mkWrapper function to create a derivation that contains a treefmt binary wrapped with your specific configuration. This avoids the need for a manual treefmt.toml file.

    Key configuration options include:

    • projectRootFile: A file used to identify the project root (e.g., .git/config).
    • programs.<name>.enable: Enables a specific formatter (e.g., programs.terraform.enable = true).
    • programs.<name>.package: Overrides the default package for a formatter with a specific version from nixpkgs.
    • settings.formatter.<name>.<option>: Passes arbitrary formatter options (like excludes) directly to the underlying tool.
    # 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" ];
    }
  4. Add a new formatter to treefmt-nix

    main

    To contribute a new formatter to the repository, follow these steps:

    1. Create the module: Add a new entry in the ./programs/ folder.
    2. Assign maintenance: Add your GitHub handle to the module's meta.maintainers list to receive pings and decision precedence.
    3. Update examples: Run ./examples.sh to update the ./examples folder.
    4. Test the formatter:
      • Temporarily enable the new formatter in the project's ./treefmt.nix file.
      • Add sample files (both well-formatted and badly-formatted) to the repository.
      • Run nix fmt. Verify that well-formatted files are unchanged and badly-formatted files are flagged. Re-run nix fmt to ensure no unexpected changes occur.
    5. Update documentation: Add the new formatter to the README list using mdsh:
      mdsh -i README.md -o README.md
      Or via Nix:
      nix run github:zimbatm/mdsh -- -i README.md -o README.md
    6. Submit PR: Revert your temporary testing changes and submit your Pull Request.
  5. Use a custom formatter

    main

    You can define your own formatters within the settings.formatter attribute in your Nix configuration. A custom formatter requires a command (the executable to run), options (an array of arguments, including any script logic), and includes (a list of file patterns the formatter should apply to).

    settings.formatter = {
      "yq-json" = {
        command = "${pkgs.bash}/bin/bash";
        options = [
          "-euc"
          ''
            for file in "$@"; do
              ${lib.getExe yq-go} -i --output-format=json $file
            done
          ''
          "--" # bash swallows the second argument when using -c
        ];
        includes = [ "*.json" ];
      };
    };
  6. View supported formatters

    main
    treefmt-nix supports over 100 formatters. You can find the Nix modules for these formatters in the ./programs/ directory of the repository. Common formatters include rustfmt, prettier, black, terraform, shellcheck, and many others.
  7. Configure treefmt-nix options

    main

    Configuration is written in Nix syntax. The following options are available:

    OptionDescription
    projectRootFileThe file used to identify the project root (e.g., .git/config or flake.nix).
    programs.<name>.enableBoolean to enable a specific formatter (e.g., programs.terraform.enable = true).
    programs.<name>.packageSpecify a particular build/version of the formatter from nixpkgs.
    settings.formatter.<name>.<option>Pass arbitrary formatter options (like excludes or includes) to the underlying tool.

    For a complete list of formatter-specific options, refer to the official treefmt documentation.