`eachSystem` in flake example makes it harder to understand
enhancement
When trying to adapt the current flake example from the README to their own project, readers have to parse out the custom (unusual?) `eachSystem` as well as other parts of the example that are specific to a particular usage. The extra input dependency is also unnecessary, and those unfamiliar with it (e.g., me) may have to go look up the `systems` repo just to figure out what the function they just pasted into their code is doing.
`eachSystem` is not the simplest and requires a bit of thinking to understand for those who haven't done much nix-lang wrangling or higher-ordered function algebra. (Even for the more experienced, it's not clear what benefit it is to have to pass a pkgs parameter when the correct nixpkgs can be deduced from the system.)
As demonstration, to mentally parse the value of the `formatter` attribute, one has to think through the following:
```nix
nixpkgs.lib.genAttrs [ "x86_64-linux" "etc" ] (
system:
(
pkgs:
(nixpkgs.lib.genAttrs [ "x86_64-linux" "etc" ] (
system: (pkgs: treefmt-nix.lib.evalModule pkgs ./treefmt.nix) nixpkgs.legacyPackages.${system}
)).${pkgs.system}.config.build.wrapper
)
nixpkgs.legacyPackages.${system}
);
```
to come to the conclusion that the wrapper is evaluated with pkgs and the config, on which the formatter and the checker can then be accessed.
I may not be the best nixer in the world, but I've been using nix for several years now and it still took me at least half an hour of rotating functions in my mind to adapt this to my own flake.
(Not to mention that to get the system's `treefmtEval`, the example gets `system` from `pkgs` — which, by the way, gives the warning that `'system' has been renamed to/replaced by 'stdenv.hostPlatform.system'` — which is gotten from `system`, which is already passed as a parameter!)
**Describe the solution you'd like**
For each individual system, the necessary code simplifies to
```nix
(treefmt-nix.lib.evalModule nixpkgs.legacyPackages.${system} ./treefmt.nix
).config.build.wrapper;
```
With this, it's clear that what is necessary to produce the formatter is to apply `treefmt-nix.lib.evalModule` to the appropriate `pkgs` and the repo languages config, which results in an attrset on which `.config.build.wrapper` is the wrapped formatter and `.config.build.check` is the checker. Having to make a wrapper where the inner argument needs an outer variable is still not the clearest UX, but that makes it even more necessary for the example to be as clear as possible.
For example:
```nix
{
inputs.treefmt-nix.url = "github:numtide/treefmt-nix";
outputs = { self, nixpkgs, systems, treefmt-nix }:
let
# substitute your preferred way of handling `system`
eachSystem = nixpkgs.lib.genAttrs [ "x86_64-linux" "etc" ];
# for each system, evaluate treefmt-nix with pkgs and your configuration
treefmtEval = eachSystem (system:
treefmt-nix.lib.evalModule nixpkgs.legacyPackages.${system} ./treefmt.nix
);
in
{
# for `nix fmt`, use `.config.build.wrapper`
formatter = eachSystem (system:
treefmtEval.${system}.config.build.wrapper
);
# for `nix flake check`, use `.config.build.check` and apply it to the flake
checks = eachSystem (system: {
formatting = treefmtEval.${system}.config.build.check self;
});
};
}
```
0 条评论