Skip to content

Commit

Permalink
WIP: add treefmt.withConfig
Browse files Browse the repository at this point in the history
This is useful if you want to configure treefmt with nix, and precisely
pass all the commands from nixpkgs.

This relies on the PRJ_ROOT environment variable to point to the project
root.
  • Loading branch information
zimbatm committed Jul 5, 2022
1 parent 51826cc commit 582c5aa
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 1 deletion.
2 changes: 2 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export PRJ_ROOT=$PWD
use nix
89 changes: 88 additions & 1 deletion default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,85 @@
, rustPackages ? nixpkgs.rustPackages
}:
let
lib = nixpkgs.lib;

cargoToml = with builtins; (fromTOML (readFile ./Cargo.toml));

# A new kind of option type that calls lib.getExe on derivations
exeType = lib.mkOptionType {
name = "exe";
description = "Path to executable";
check = (x: lib.isString x || lib.isPath x || lib.isDerivation x);
merge = loc: defs:
let res = lib.mergeOneOption loc defs; in
if lib.isString res || lib.isPath res then
"${res}"
else
lib.getExe res;
};

# The schema of the treefmt.toml data structure.
configSchema = with lib; {
excludes = mkOption {
description = "A global list of paths to exclude. Supports glob.";
type = types.listOf types.str;
default = [ ];
example = [ "./node_modules/**" ];
};

formatter = mkOption {
type = types.attrsOf (types.submodule [{
options = {
command = mkOption {
description = "Executable obeying the treefmt formatter spec";
type = exeType;
};

options = mkOption {
description = "List of arguments to pass to the command";
type = types.listOf types.str;
default = [ ];
};

includes = mkOption {
description = "List of files to include for formatting. Supports globbing.";
type = types.listOf types.str;
};

excludes = mkOption {
description = "List of files to exclude for formatting. Supports globbing. Takes precedence over the includes.";
type = types.listOf types.str;
default = [ ];
};
};
}]);
default = { };
description = "Set of formatters to use";
};
};

configFormat = nixpkgs.formats.toml { };

# Use the Nix module system to validate the treefmt config file format.
evalConfig = settings:
lib.evalModules {
modules = [
({ config, ... }: {
options.settings = configSchema;
options.configFile = lib.mkOption { type = lib.types.path; };
config.settings = settings;
config.configFile = configFormat.generate "treefmt.toml" config.settings;
})
];
};

# Pass treefmt setting options as Nix data, and get back a treefmt.toml file.
mkConfig = settings:
let
mod = evalConfig settings;
in
mod.config.configFile;

# What is used when invoking `nix run github:numtide/treefmt`
treefmt = rustPackages.rustPlatform.buildRustPackage {
inherit (cargoToml.package) name version;
Expand All @@ -32,13 +109,23 @@ let
cargoLock.lockFile = ./Cargo.lock;

meta.description = "one CLI to format the code tree";

passthru.withConfig = { ... }@settings:
let
configFile = mkConfig settings;
in
nixpkgs.writeShellScriptBin "treefmt" ''
exec ${treefmt}/bin/treefmt --config-file ${configFile} "$@"
'';
};

# Add all the dependencies of treefmt, plus more build tools
devShell = treefmt.overrideAttrs (prev: {
shellHook = ''
# Put the treefmt binary on the PATH when it's built
export PATH=$PWD/target/debug:$PATH
# Point to the project root
export PRJ_ROOT=$PWD
'';

nativeBuildInputs = prev.nativeBuildInputs ++ (with nixpkgs; [
Expand Down Expand Up @@ -66,7 +153,7 @@ let
});
in
{
inherit treefmt devShell;
inherit treefmt devShell evalConfig mkConfig;

# A collection of packages for the project
docs = nixpkgs.callPackage ./docs { };
Expand Down
5 changes: 5 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@

packages = pkgs;

# In Nix 2.8 you can run `nix fmt` to format this whole repo. Note that you need to have loaded the
# `nix develop` shell before so the various formatters are available in the PATH.
# It also assumes that the PRJ_ROOT environment variable is set that points to the project root.
formatter = pkgs.treefmt.withConfig (nixpkgs.lib.importTOML ./treefmt.toml);

devShell = pkgs.devShell;
}
);
Expand Down

0 comments on commit 582c5aa

Please sign in to comment.