From 01b66aa5d0b825553ceb0227955f547a04b699c8 Mon Sep 17 00:00:00 2001 From: zimbatm Date: Fri, 20 May 2022 16:02:45 +0200 Subject: [PATCH] WIP: add treefmt.withConfig This is useful if you want to configure treefmt with nix, and precisely pass all the commands from nixpkgs. --- .envrc | 2 ++ default.nix | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++- flake.nix | 5 +++ 3 files changed, 95 insertions(+), 1 deletion(-) create mode 100644 .envrc diff --git a/.envrc b/.envrc new file mode 100644 index 00000000..994e189c --- /dev/null +++ b/.envrc @@ -0,0 +1,2 @@ +export PRJ_ROOT=$PWD +use nix diff --git a/default.nix b/default.nix index 09895b61..f04d5d58 100644 --- a/default.nix +++ b/default.nix @@ -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; @@ -32,6 +109,14 @@ 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 @@ -39,6 +124,8 @@ let 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; [ @@ -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 { }; diff --git a/flake.nix b/flake.nix index c45c90ae..ca8695bd 100644 --- a/flake.nix +++ b/flake.nix @@ -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; } );