Skip to content

Commit

Permalink
Merge pull request #169 from numtide/withConfig
Browse files Browse the repository at this point in the history
add treefmt.withConfig
  • Loading branch information
zimbatm authored Sep 21, 2022
2 parents ef8f965 + 8467716 commit 9615c40
Show file tree
Hide file tree
Showing 5 changed files with 165 additions and 8 deletions.
7 changes: 7 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -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
26 changes: 25 additions & 1 deletion default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
Expand Down Expand Up @@ -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 { };
Expand Down
12 changes: 6 additions & 6 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

15 changes: 14 additions & 1 deletion flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -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 changes: 113 additions & 0 deletions module-options.nix
Original file line number Diff line number Diff line change
@@ -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"
'';
};
};

0 comments on commit 9615c40

Please sign in to comment.