treefmt icon indicating copy to clipboard operation
treefmt copied to clipboard

Using treefmt in flake projects

Open srid opened this issue 2 years ago • 6 comments

I'd like to minimize the Nix stub required to use treefmt in my projects. Presently, there is a ~40 line nix that provides me nix run .#format (runs treefmt in project tree) as well a flake check that is built in CI. Could these be upstreamed to treefmt's flake in some way such that I can use it as a flake input, and directly use those app and check without replicating it in every project? Or is there a better approach to this?

Here's the ~40 line Nix:

{ inputs, system, pkgs }:

# Uses https://github.com/numtide/treefmt to provide auto-formating for multiple
# languages. Configure the behaviour in treefmt.toml at project root.
rec {
  dependencies = [
    pkgs.haskellPackages.cabal-fmt
    pkgs.haskellPackages.fourmolu
    pkgs.treefmt
  ];

  apps = {
    format = {
      type = "app";
      program = pkgs.writeShellApplication
        {
          name = "format";
          runtimeInputs = dependencies;
          text = "treefmt";
        } + "/bin/format";
    };
  };

  checks = {
    # Checks that the project tree is *already* formatted.
    format = pkgs.runCommandLocal "format-check"
      {
        buildInputs = dependencies;
      } ''
      set -e
      # treefmt maintains a cache at ~/.cache; so use $TMP as home.
      # treefmt 0.4 has a --no-cache option, but our nixpkgs has only 0.3
      export HOME=$TMP
      treefmt -vvv --clear-cache --fail-on-change -C ${inputs.self}
      touch $out
    '';
  };
}

I imagine we want to parameterize this over 'dependencies'.

srid avatar May 11 '22 15:05 srid

What if even the config could be declared in Nix.

pkgs.treefmt.withConfig {
  formatters.ruby = {
    command = ["${pkgs.rubocop}/bin/rubocop"];
    includes = [ "*.rb" ];
  };
}

zimbatm avatar May 11 '22 17:05 zimbatm

@zimbatm That's a great idea ... but, while it would get rid of dependencies, I'd still have to hand-write apps.format and checks.format.

srid avatar May 12 '22 00:05 srid

Yup. That shape depends on how the systems get abstracted away.

Nix 2.8 also has a formatters.<system> = <installable> interface so you could run nix fmt that then invokes treefmt, that then invokes the rest :p (not saying it's a great idea, just reporting for now)

zimbatm avatar May 12 '22 07:05 zimbatm

I would prefer to see nix fmt win, seems like the right approach.

MatthewCroughan avatar May 12 '22 15:05 MatthewCroughan

IIUC nix fmt is about formatting *.nix files only, and not other languages?

Unless we make nix fmt language-agnostic, but that may well involve upstreaming treefmt as the 'backend' to implement it in nixpkgs.

srid avatar May 12 '22 15:05 srid

Technically, nix fmt leaves the filesystem traversal up to the tool. But I don't know if that is an invariant or not. (and also if it's a good idea).

zimbatm avatar May 13 '22 11:05 zimbatm

I think we can retire this issue. https://github.com/numtide/treefmt-nix + flake-parts is now a pretty answer to this question, thanks to the help of @srid

zimbatm avatar Dec 28 '22 11:12 zimbatm