1
1
forked from extern/flakelight
flakelight/builtinModules/formatter.nix
Archit Gupta efcf01325b Enable faster building of formatter
Since the formatter always depended on devShell packages, building the
formatter involved building all the devShell packages, which can be
slow.

In the case where formatters are set to plain strings, such as
"nixpkgs-fmt", depending on the devShell packages is necessary in order
to put the formatting utility on the path. But when a formatters option
is set to an package, such as "${pkgs.nixpkgs-fmt}/bin/nixpkgs-fmt",
then that formatter option does not depend on the devShell packages.

Flakelight now detects if any of the configured formatters are using the
first form, and only if so does it add the devShell packages dependency.
This allows the first form to still work, without incurring a cost for
flakes that only use the second form.

Users can use the second form for all formatters options if they wish to
not build the devShell packages when using the formatter.
2024-02-19 02:35:16 -08:00

66 lines
2.1 KiB
Nix

# flakelight -- Framework for simplifying flake setup
# Copyright (C) 2023 Archit Gupta <archit@accelbread.com>
# SPDX-License-Identifier: MIT
{ config, src, lib, flakelight, genSystems, ... }:
let
inherit (builtins) all hasContext;
inherit (lib) mkDefault mkMerge mkOption mkIf mapAttrsToList;
inherit (lib.types) functionTo lazyAttrsOf package str;
inherit (flakelight.types) nullable optFunctionTo;
in
{
options = {
formatter = mkOption {
type = nullable (functionTo package);
default = null;
};
formatters = mkOption {
type = nullable (optFunctionTo (lazyAttrsOf str));
default = null;
};
};
config = mkMerge [
(mkIf (config.formatter != null) {
outputs.formatter = genSystems config.formatter;
})
(mkIf (config.formatters != null) {
outputs.formatter = mkDefault (genSystems
({ pkgs, lib, fd, coreutils, ... }:
let
inherit (lib) attrValues makeBinPath;
formatters = config.formatters pkgs;
fullContext = all hasContext (attrValues formatters);
packages =
if config.devShell == null then [ ]
else (config.devShell pkgs).packages pkgs;
caseArms = toString (mapAttrsToList
(n: v: "\n ${n}) ${v} \"$f\" & ;;")
formatters);
in
pkgs.writeShellScriptBin "formatter" ''
PATH=${if fullContext then "" else makeBinPath packages}
for f in "$@"; do
if [ -d "$f" ]; then
${fd}/bin/fd "$f" -Htf -x "$0" &
else
case "$(${coreutils}/bin/basename "$f")" in${caseArms}
esac
fi
done &>/dev/null
wait
''));
})
(mkIf ((config.formatters != null) || (config.formatter != null)) {
checks.formatting = { lib, outputs', diffutils, ... }: ''
${lib.getExe outputs'.formatter} .
${diffutils}/bin/diff -qr ${src} . |\
sed 's/Files .* and \(.*\) differ/File \1 not formatted/g'
'';
})
];
}