diff --git a/README.md b/README.md index 68b87008..62352f27 100644 --- a/README.md +++ b/README.md @@ -219,6 +219,7 @@ This repo contains a top-level `default.nix` that returns the library helper fun * ocamlformat * opa * ormolu +* packer * php-cs-fixer * prettier * protolint @@ -278,14 +279,20 @@ PRs to add new formatters are welcome! In order to add a new formatter do the following things: -1. Create a new entry in the ./programs/ folder. -3. Run `./examples.sh` to update the ./examples folder. -4. To test the program: - 1. Extend the project's `./treefmt.nix` file (temporarily) - 2. Add a bunch of sources in this repo - 3. Run `nix fmt` +1. Create a new entry in the `./programs/` folder. +2. Run `./examples.sh` to update the `./examples` folder. +3. To test the program: + 1. Extend the project's `./treefmt.nix` file (temporarily) to enable the + new formatter and configure it in whatever manner is appropriate. + 2. Add a bunch of pertinent sources in this repo -- for instance, if the + new formatter is meant to format `*.foo` files, add a number of `*.foo` + files, some well-formatted (and therefore expected to + be exempt from modification by `treefmt`) and some badly-formatted. + 3. Run `nix fmt`. Confirm that well-formatted files are unchanged and that + badly-formatted files are flagged as such. Re-run `nix fmt` and confirm + that no additional changes were made. 4. Once this is good, revert those changes. -5. Submit the PR! +4. Submit the PR! ## Commercial support diff --git a/examples/formatter-packer.toml b/examples/formatter-packer.toml new file mode 100644 index 00000000..ebdea636 --- /dev/null +++ b/examples/formatter-packer.toml @@ -0,0 +1,6 @@ +# Example generated by ../examples.sh +[formatter.packer] +command = "treefmt-nix-packer-fmt-wrapper" +excludes = [] +includes = ["*.pkr.hcl", "*.pkrvars.hcl"] +options = ["--"] diff --git a/programs/packer.nix b/programs/packer.nix new file mode 100644 index 00000000..76069abc --- /dev/null +++ b/programs/packer.nix @@ -0,0 +1,61 @@ +{ lib, pkgs, config, ... }: +let + cfg = config.programs.packer; + + # `packer fmt` accepts only a single template as an argument: + # > $ packer fmt -h |& head -n 1 + # > Usage: packer fmt [options] [TEMPLATE] + # `packer fmt` supports recursively formatting all `*.pkr.hcl` and + # `*.pkrvars.hcl` files in a specified directory, but since we want to + # control the exact list of files-to-be-formatted, we instead have to invoke + # `packer fmt` once per selected file. Consequently, we need a means of + # distinguishing which arguments are options (from + # `settings.formatter.packer.options`) and which are filenames; this is so + # that we can pass all options to each `packer fmt`. The traditional `--` + # sequence suits this purpose. + command = pkgs.writers.writeBashBin "treefmt-nix-packer-fmt-wrapper" '' + set -eu + + declare -a opts + saw_separator=0 + while (( "$#" > 0 )); do + if [[ "$1" = -- ]]; then + saw_separator=1 + shift + break + fi + + opts+=("$1") + shift + done + + if [[ "$saw_separator" = 0 ]]; then + echo 1>&2 "\ + Error: ''${0##*/}: the end-of-options separator sequence is missing. + Please ensure that the final entry in 'settings.formatter.packer.options' is a bare double-dash ('--'). + Otherwise, this program cannot determine which arguments are options to 'packer fmt' and which are filenames." + exit 1 + fi + + rc=0 + for tmpl in "$@"; do + ${lib.escapeShellArg cfg.package}/bin/packer fmt "''${opts[@]}" "$tmpl" || rc="$?" + done + + exit "''${rc:-0}" + ''; +in +{ + options.programs.packer = { + enable = lib.mkEnableOption "packer"; + package = lib.mkPackageOption pkgs "packer" { }; + }; + + config = lib.mkIf cfg.enable { + settings.formatter.packer = { + inherit command; + options = lib.mkAfter [ "--" ]; + includes = [ "*.pkr.hcl" "*.pkrvars.hcl" ]; + }; + }; +}