Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
113 changes: 75 additions & 38 deletions pkgs/by-name/ni/nixfmt-tree/package.nix
Original file line number Diff line number Diff line change
@@ -1,45 +1,61 @@
{
lib,
runCommand,
buildEnv,
makeWrapper,
writers,
treefmt,
nixfmt-rfc-style,
nixfmt-tree,

settings ? {
# The default is warn, which would be too annoying for people who just care about Nix
on-unmatched = "info";
# Assumes the user is using Git, fails if it's not
tree-root-file = ".git/index";

formatter.nixfmt = {
command = "nixfmt";
includes = [ "*.nix" ];
};
},
runtimePackages ? [
nixfmt-rfc-style
],
}:
buildEnv {
name = "nixfmt-tree";

# Allows this derivation to be used as a shell providing both treefmt and nixfmt
paths = [ treefmt ] ++ runtimePackages;
pathsToLink = [ "/bin" ];

nativeBuildInputs = [
makeWrapper
];

postBuild = ''
wrapProgram $out/bin/treefmt \
--prefix PATH : $out/bin \
--add-flags "--config-file ${writers.writeTOML "treefmt.toml" settings}"
'';
settings ? { },
runtimeInputs ? [ ],
nixfmtPackage ? nixfmt-rfc-style,

# NOTE: `runtimePackages` is deprecated. Use `nixfmtPackage` and/or `runtimeInputs`.
runtimePackages ? [ nixfmtPackage ],
}@args:
let
allRuntimeInputs = runtimePackages ++ runtimeInputs;

# Tests whether a package's main program is nixfmt.
isNixfmt = p: p.meta.mainProgram or null == "nixfmt";

treefmtWithConfig = treefmt.withConfig {
name = "nixfmt-tree";

settings = [
# Default settings
{
_file = ./package.nix;

# Log level for files treefmt won't format
# The default is warn, which would be too annoying for people who just care about Nix
on-unmatched = lib.mkOptionDefault "info";

# Assume the tree is a Git repository, will fail if it's not
tree-root-file = lib.mkOptionDefault ".git/index";

# NOTE: The `mkIf` condition should not be needed once `runtimePackages` is removed.
formatter.nixfmt = lib.mkIf (lib.any isNixfmt allRuntimeInputs) {
command = "nixfmt";
includes = [ "*.nix" ];
};
}
# User supplied settings
{
_file = "<nixfmt-tree args>";
imports = lib.toList settings;
}
];

runtimeInputs =
# Handle `runtimePackages` deprecation (added 2025-04-01)
lib.warnIf (args ? runtimePackages) ''
nixfmt-tree: overriding `runtimePackages` is deprecated, use `runtimeInputs` instead.
Note: you do not need to supply a nixfmt package when using `runtimeInputs`, however you can override `nixfmtPackage` to a different nixfmt package.
For additional flexibility, or to configure treefmt without nixfmt, consider using `treefmt.withConfig` instead of `nixfmt-tree`.
'' allRuntimeInputs;
};
in
treefmtWithConfig.overrideAttrs {
meta = {
mainProgram = "treefmt";
description = "Official Nix formatter zero-setup starter using treefmt";
Expand All @@ -62,7 +78,7 @@ buildEnv {
```

You can then also use `treefmt` in a pre-commit/pre-push [Git hook](https://git-scm.com/docs/githooks)
and `nixfmt` with your editors format-on-save feature.
and with your editor's format-on-save feature.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah so this was the original motivation for including the formatter binaries as well, but as explained in the last formatting team meeting, people should be using treefmt even for format-on-save, because treefmt knows about the options you format the codebase with :)


- To check formatting in CI, run the following in a checkout of your Git repository:
```
Expand All @@ -71,9 +87,30 @@ buildEnv {

For more flexibility, you can customise this package using
```nix
nixfmt-tree.override {
settings = { /* treefmt config */ };
runtimePackages = [ /* List any formatters here */ ];
pkgs.nixfmt-tree.override {
settings = { /* additional treefmt config */ };
runtimeInputs = [ /* additional formatter packages */ ];
}
```

You can achieve similar results by manually configuring `treefmt`:
```nix
pkgs.treefmt.withConfig {
runtimeInputs = [ pkgs.nixfmt-rfc-style ];

settings = {
# Log level for files treefmt won't format
on-unmatched = "info";

# Assume the tree is a Git repository, will fail if it's not
tree-root-file = ".git/index";

# Configure nixfmt for .nix files
formatter.nixfmt = {
command = "nixfmt";
includes = [ "*.nix" ];
};
};
}
```

Expand Down