numtide / treefmt

one CLI to format your repo [maintainers=@zimbatm,@brianmcgee]
https://treefmt.com
MIT License
575 stars 35 forks source link

Using treefmt in flake projects #165

Closed srid closed 1 year ago

srid commented 2 years ago

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'.

zimbatm commented 2 years ago

What if even the config could be declared in Nix.

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

@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.

zimbatm commented 2 years ago

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)

MatthewCroughan commented 2 years ago

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

srid commented 2 years ago

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.

zimbatm commented 2 years ago

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 commented 1 year ago

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