diff --git a/README.md b/README.md index ac2c69938..ba7cc528e 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,9 @@ Running ``devenv init`` generates ``devenv.nix``: # https://devenv.sh/pre-commit-hooks/ pre-commit.hooks.shellcheck.enable = true; + # https://devenv.sh/treefmt/ + treefmt.programs.nixpkgs-fmt.enable = true; + # https://devenv.sh/processes/ processes.ping.exec = "ping localhost"; } diff --git a/devenv.lock b/devenv.lock index 6649152f4..97664d600 100644 --- a/devenv.lock +++ b/devenv.lock @@ -155,6 +155,22 @@ "type": "github" } }, + "nixpkgs_2": { + "locked": { + "lastModified": 1718895438, + "owner": "nixos", + "repo": "nixpkgs", + "rev": "d603719ec6e294f034936c0d0dc06f689d91b6c3", + "treeHash": "5431d5da7bc85049065fe5a6ac014ed1d2b9abe4", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, "pre-commit-hooks": { "inputs": { "flake-compat": "flake-compat_2", @@ -184,7 +200,8 @@ "devenv": "devenv", "nix": "nix", "nixpkgs": "nixpkgs", - "pre-commit-hooks": "pre-commit-hooks" + "pre-commit-hooks": "pre-commit-hooks", + "treefmt-nix": "treefmt-nix" } }, "systems": { @@ -201,6 +218,24 @@ "repo": "default", "type": "github" } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": "nixpkgs_2" + }, + "locked": { + "lastModified": 1718522839, + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "68eb1dc333ce82d0ab0c0357363ea17c31ea1f81", + "treeHash": "3a739f95f5906aab649d47fe4832696cc9f87de5", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } } }, "root": "root", diff --git a/devenv.nix b/devenv.nix index 2c0033990..493b4a433 100644 --- a/devenv.nix +++ b/devenv.nix @@ -138,12 +138,22 @@ ''; }; + #enable tree fmt + treefmt = { + projectRootFile = "devenv.nix"; + programs = { + nixpkgs-fmt.enable = true; + rustfmt.enable = true; + }; + }; + pre-commit.hooks = { - nixpkgs-fmt.enable = true; #shellcheck.enable = true; #clippy.enable = true; - rustfmt.enable = true; #markdownlint.enable = true; + treefmt = { + enable = true; + }; markdownlint.settings.configuration = { MD013 = { line_length = 120; diff --git a/devenv/src/flake.tmpl.nix b/devenv/src/flake.tmpl.nix index bcc9f7f0b..aec22570b 100644 --- a/devenv/src/flake.tmpl.nix +++ b/devenv/src/flake.tmpl.nix @@ -5,6 +5,7 @@ in { pre-commit-hooks.url = "github:cachix/pre-commit-hooks.nix"; pre-commit-hooks.inputs.nixpkgs.follows = "nixpkgs"; + treefmt-nix.url = "github:numtide/treefmt-nix"; nixpkgs.url = "github:cachix/devenv-nixpkgs/rolling"; devenv.url = "github:cachix/devenv?dir=src/modules"; } // (if builtins.pathExists (devenv_dotfile + "/flake.json") diff --git a/docs/treefmt.md b/docs/treefmt.md new file mode 100644 index 000000000..c0f652d8f --- /dev/null +++ b/docs/treefmt.md @@ -0,0 +1,73 @@ +# `devenv` Integration for [treefmt](https://treefmt.com/) via [treefmt-nix](https://github.com/numtide/treefmt-nix) + +## Set up + +Check the available integrations in [the list of all available integrations](reference/options.md#treefmt). + +Add your desired integration to your `devenv.nix` file. For example, the following code would enable `treefmt` with the `nixpkgs-fmt` and `rustfmt` integrations: + +```nix +{ inputs, ... }: + +{ + treefmt = { + projectRootFile = "devenv.nix"; + programs = { + nixpkgs-fmt.enable = true; + rustfmt.enable = true; + }; + }; +} +``` + +### In Action: + +```shell-session +$ devenv shell +Building shell ... +Entering shell ... + +treefmt # This would run treefmt on all files. +``` + +## Additional Devenv Integrations + +### Pre-commit Hooks + +If you would like to enable `treefmt` in your pre-commit hooks, simply add: + +```nix +{ inputs, ... }: + +{ + pre-commit.hooks = { + treefmt.enable = true; + }; +} +``` + +This will enable `treefmt` hooks and automatically change the default package to the one you have defined in your `devenv`. + +## Using a Custom Formatter + +It is also possible to use custom formatters with `treefmt-nix`. For example, the following custom formatter formats JSON files using `yq-go`: + +```nix +{ + treefmt.settings.formatter = { + "yq-json" = { + command = "${pkgs.bash}/bin/bash"; + options = [ + "-euc" + '' + for file in "$@"; do + ${lib.getExe yq-go} -i --output-format=json $file + done + '' + "--" # bash swallows the second argument when using -c + ]; + includes = [ "*.json" ]; + }; + }; +} +``` diff --git a/flake.lock b/flake.lock index 9e5f4d02f..0a51302c9 100644 --- a/flake.lock +++ b/flake.lock @@ -354,7 +354,8 @@ "flake-compat": "flake-compat_2", "nix": "nix_2", "nixpkgs": "nixpkgs_2", - "pre-commit-hooks": "pre-commit-hooks" + "pre-commit-hooks": "pre-commit-hooks", + "treefmt-nix": "treefmt-nix" } }, "systems": { @@ -386,6 +387,26 @@ "repo": "default", "type": "github" } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1718522839, + "narHash": "sha256-ULzoKzEaBOiLRtjeY3YoGFJMwWSKRYOic6VNw2UyTls=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "68eb1dc333ce82d0ab0c0357363ea17c31ea1f81", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } } }, "root": "root", diff --git a/flake.nix b/flake.nix index d456b04eb..2d257dd3c 100644 --- a/flake.nix +++ b/flake.nix @@ -14,6 +14,12 @@ flake-compat.follows = "flake-compat"; }; }; + inputs.treefmt-nix = { + url = "github:numtide/treefmt-nix"; + inputs = { + nixpkgs.follows = "nixpkgs"; + }; + }; inputs.flake-compat = { url = "github:edolstra/flake-compat"; flake = false; @@ -35,7 +41,7 @@ }; - outputs = { self, nixpkgs, pre-commit-hooks, nix, ... }@inputs: + outputs = { self, nixpkgs, pre-commit-hooks, treefmt-nix, nix, ... }@inputs: let systems = [ "x86_64-linux" "i686-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ]; forAllSystems = f: builtins.listToAttrs (map (name: { inherit name; value = f name; }) systems); @@ -49,11 +55,12 @@ ./src/modules/top-level.nix { devenv.warnOnNewVersion = false; } ]; - specialArgs = { inherit pre-commit-hooks pkgs inputs; }; + specialArgs = { inherit pre-commit-hooks treefmt-nix pkgs inputs; }; }; sources = [ { name = "${self}"; url = "https://github.com/cachix/devenv/blob/main"; } { name = "${pre-commit-hooks}"; url = "https://github.com/cachix/pre-commit-hooks.nix/blob/master"; } + { name = "${treefmt-nix}"; url = "https://github.com/numtide/treefmt-nix/blob/main"; } ]; rewriteSource = decl: let diff --git a/src/modules/integrations/treefmt.nix b/src/modules/integrations/treefmt.nix new file mode 100644 index 000000000..46356984d --- /dev/null +++ b/src/modules/integrations/treefmt.nix @@ -0,0 +1,21 @@ +{ pkgs, self, lib, inputs, config, ... }: { + + options.treefmt = lib.mkOption { + type = lib.types.submoduleWith { + modules = inputs.treefmt-nix.lib.submodule-modules; + specialArgs = { inherit pkgs; }; + shorthandOnlyDefinesConfig = true; + }; + default = { }; + description = "Integration of https://github.com/numtide/treefmt-nix"; + }; + + config = lib.mkIf ((lib.filterAttrs (id: value: value.enable) config.treefmt.programs) != { }) { + packages = [ + config.treefmt.build.wrapper + ]; + + #automatically add treefmt-nix to pre-commit if the user enables it. + pre-commit.hooks.treefmt.package = lib.mkForce config.treefmt.build.wrapper; + }; +}