Merge pull request #169 from numtide/withConfig

add treefmt.withConfig
This commit is contained in:
Jonas Chevalier 2022-09-21 18:54:15 +02:00 committed by GitHub
commit 9615c40924
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 165 additions and 8 deletions

7
.envrc Executable file
View File

@ -0,0 +1,7 @@
#!/usr/bin/env bash
# Environment variables for the project. See https://direnv.net/
if nix flake metadata &>/dev/null; then
use flake
else
use nix
fi

View File

@ -13,6 +13,18 @@ let
cargoToml = with builtins; (fromTOML (readFile ./Cargo.toml));
# Use the Nix module system to validate the treefmt config file format.
evalModule = config:
lib.evalModules {
modules = [
{
_module.args = { inherit nixpkgs lib treefmt; };
}
./module-options.nix
config
];
};
# What is used when invoking `nix run github:numtide/treefmt`
treefmt = rustPackages.rustPlatform.buildRustPackage {
inherit (cargoToml.package) name version;
@ -34,6 +46,12 @@ let
cargoLock.lockFile = ./Cargo.lock;
meta.description = "one CLI to format the code tree";
passthru.withConfig = config:
let
mod = evalModule config;
in
mod.config.build.wrapper;
};
# Add all the dependencies of treefmt, plus more build tools
@ -68,7 +86,13 @@ let
});
in
{
inherit treefmt devShell;
inherit treefmt devShell evalModule;
# module that generates and wraps the treefmt config with Nix
module = ./module-options.nix;
# reduce a bit of repetition
inherit (treefmt.passthru) withConfig;
# A collection of packages for the project
docs = nixpkgs.callPackage ./docs { };

View File

@ -7,11 +7,11 @@
]
},
"locked": {
"lastModified": 1661009076,
"narHash": "sha256-phAE40gctVygRq3G3B6LhvD7u2qdQT21xsz8DdRDYFo=",
"lastModified": 1663686189,
"narHash": "sha256-cgWGo0SLM4RX0DqodeFHsU0PRGlmz6AOSF1lmX21bvg=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "850d8a76026127ef02f040fb0dcfdb8b749dd9d9",
"rev": "f17e9dba098c0a7bca10029bec5384fd6425c157",
"type": "github"
},
"original": {
@ -22,11 +22,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1661239106,
"narHash": "sha256-C5OCLnrv2c4CHs9DMEtYKkjJmGL7ySAZ1PqPkHBonxQ=",
"lastModified": 1663669617,
"narHash": "sha256-yUrzkRDc6P3hsI5TdQ5+q8gnyjadNvaM3MMEsEVS8qk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "963d27a0767422be9b8686a8493dcade6acee992",
"rev": "41ac0bd371618db6dd67fd952cc5b3d6a9955a15",
"type": "github"
},
"original": {

View File

@ -18,9 +18,22 @@
};
in
{
inherit packages;
# This contains a mix of packages, modules, ...
legacyPackages = packages;
devShells.default = packages.devShell;
# In Nix 2.8 you can run `nix fmt` to format this whole repo.
#
# Because we load the treefmt.toml and don't define links to the
# packages in Nix, the formatter has to run inside of `nix develop`
# to have the various tools on the PATH.
#
# It also assumes that the project root has a flake.nix (override this by setting `projectRootFile`).
formatter = packages.treefmt.withConfig {
settings = nixpkgs.lib.importTOML ./treefmt.toml;
projectRootFile = "flake.nix";
};
};
};
}

113
module-options.nix Normal file
View File

@ -0,0 +1,113 @@
{ lib, nixpkgs, treefmt, ... }:
let
# 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 || builtins.isPath x || lib.isDerivation x);
merge = loc: defs:
let res = lib.mergeOneOption loc defs; in
if lib.isString res || builtins.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 { };
in
{
# Schema
options = {
settings = configSchema;
package = lib.mkOption {
description = "Package wrapped in the build.wrapper output";
type = lib.types.package;
default = treefmt;
};
projectRootFile = lib.mkOption {
description = ''
File to look for to determine the root of the project in the
build.wrapper.
'';
example = "flake.nix";
};
# Outputs
build = {
configFile = lib.mkOption {
description = ''
Contains the generated config file derived from the settings.
'';
type = lib.types.path;
};
wrapper = lib.mkOption {
description = ''
The treefmt package, wrapped with the config file.
'';
type = lib.types.package;
};
};
};
# Config
config.build = {
configFile = configFormat.generate "treefmt.toml" config.settings;
wrapper = nixpkgs.writeShellScriptBin "treefmt" ''
find_up() (
ancestors=()
while [[ ! -f "$1" ]]; do
ancestors+=("$PWD")
if [[ $PWD == / ]]; then
echo "ERROR: Unable to locate the projectRootFile ($1) in any of: ''${ancestors[*]@Q}" >&2
exit 1
fi
cd ..
done
)
tree_root=$(find_up "${config.projectRootFile}")
exec ${config.package}/bin/treefmt --config-file ${config.build.configFile} "$@" --tree-root "$tree_root"
'';
};
};