treefmt icon indicating copy to clipboard operation
treefmt copied to clipboard

Advice for how to use `treefmt` as a pre-commit hook

Open ocharles opened this issue 2 years ago • 4 comments

Is your feature request related to a problem? Please describe.

treefmt looks like a great choice for a pre-commit hook. I'd like to know the options to do this.

Describe the solution you'd like

A wiki entry/example pre-commit hook script.

Describe alternatives you've considered

A bit of Googling how to write pre-commit hooks in general.

ocharles avatar May 09 '22 08:05 ocharles

Related to https://github.com/numtide/treefmt/issues/78

zimbatm avatar May 11 '22 14:05 zimbatm

https://github.com/numtide/treefmt/blob/master/contrib/pre-commit

blaggacao avatar May 30 '22 19:05 blaggacao

https://github.com/cachix/pre-commit-hooks.nix Seems to be an obvious candidate, composing the above library that provides the changed files to arbitrary cli scripts/binaries (like treefmt).

Using https://github.com/cachix/pre-commit-hooks.nix#nix-flakes-support as a basis, just do:

checks = {
  pre-commit-check = pre-commit-hooks.lib."${system}".run {
    src = ./.;
    hooks = {
      treefmt = {
        name = "treefmt";
        enable = true;
        description = "One CLI to format the code tree.";
        types = [ "file" ];
        pass_filenames = true;
        entry = "${pkgs.treefmt}/bin/treefmt";
      };
    };
  };
};

I guess this could be added trivially, to the existing set of modules, almost verbatim: https://github.com/cachix/pre-commit-hooks.nix/blob/master/modules/hooks.nix#L327

With this I would consider this issue resolved, works well for our use-case.

thenonameguy avatar Jun 16 '22 14:06 thenonameguy

I'm using https://github.com/cachix/pre-commit-hooks.nix, but I had to make one change to the above. treefmt won't be able to access any of its formatters if they aren't already on PATH which causes the check to fail. It can still function as a devShell's shellHook, but I had to use makeWrapper to provide the path if I wanted it to function as a check.

    formatters = [
      pkgs.alejandra
      pkgs.rustfmt
    ];

    # wrap treefmt to provide the correct PATH with all formatters
    treefmt = pkgs.stdenv.mkDerivation {
      name = "treefmt";
      buildInputs = [pkgs.makeWrapper];
      buildCommand = ''
        makeWrapper \
          ${pkgs.treefmt}/bin/treefmt \
          $out/bin/treefmt \
          --prefix PATH : ${lib.makeBinPath formatters}
      '';
    };

Using this treefmt in the hook's entry line works for both checks and devShells.

edit: Even better, after writing this comment I looked in to it and they already have treefmt support and an example to use it. It looks much cleaner using writeShellApplication instead of makeWrapper https://github.com/cachix/pre-commit-hooks.nix/blob/fb58866e20af98779017134319b5663b8215d912/modules/hooks.nix#L386

justinrubek avatar Apr 29 '23 22:04 justinrubek