Crates.io | nixpkgs-fmt-rnix |
lib.rs | nixpkgs-fmt-rnix |
version | 1.2.0 |
source | src |
created_at | 2021-12-24 12:00:28.729644 |
updated_at | 2021-12-24 12:00:28.729644 |
description | Nix code formatter for nixpkgs |
homepage | |
repository | https://github.com/nix-community/nixpkgs-fmt |
max_upload_size | |
id | 502647 |
size | 186,099 |
STATUS: beta
This project's goal is to format the nix code in nixpkgs to increase the consistency of the code found there. Ideally automatically with pre-commit hooks and later ofborg enforcing the format.
You can try nixpkgs-fmt in your browser. The page also provides a way for you to submit code samples if you find the output not satisfying: https://nix-community.github.io/nixpkgs-fmt/
You might ask yourself; why do we need yet another nix code formatter?
The main goal of nixpkgs-fmt is to provide some overall consistency in the nix code submitted to nixpkgs, our main package repository.
At this point it's important to understand that there are multiple possible outputs for a code formatter. Those outputs will depend on multiple conflicting desires and depending on how much weight is being put on each requirement the output will change.
For nixpkgs-fmt we have a few of these:
Corollary rules:
At the time where we started this project none of the other formatters were weighted that way.
To implement this, we needed a whitespace and comment-preserving parser which rnix provides to us. Then create an engine that follows the AST and patches the tree with rewrite rules. The nice thing about this design is that it also works on incomplete or broken nix code. We are able to format up to the part that is missing/broken, which makes it great for potential editor integration.
Most of the other formatters out there take a pretty-printing approach where the AST is parsed, and then a pretty-printer inspects and formats the AST back to code without taking spaces and newlines into account. The advantage is that it's initially easier to implement. The output is very strict and the same AST will always give the same output. One disadvantage is that the pretty-printer needs to handle all the possible combination of Nix code to make them look good.
With nixpkgs-fmt the output will depend on how the code was formatted initially. The developer still has some input on how they want to format their code. If there is no rule for a complicated case, the code will be left alone. For nixpkgs this approach will be preferable since it minimizes the diff.
Well done for reading all of this, I hope this clarifies a bit why nixpkgs-fmt exists and what role it can play.
$ nixpkgs-fmt --help 2>&1 || true
nixpkgs-fmt 0.9.0
Format Nix code
USAGE:
nixpkgs-fmt [FLAGS] [FILE]...
FLAGS:
--check Only test if the formatter would produce differences
--explain Show which rules are violated
-h, --help Prints help information
--output-format Output syntax tree in JSON format
--parse Show syntax tree instead of reformatting
-V, --version Prints version information
ARGS:
<FILE>... File to reformat in place. If no file is passed, read from stdin.
When nixpkgs-fmt
is given a folder as a file argument, it will traverse that
using the same ignore crate as ripgrep,
using 8 parallel threads.
By default it will automatically ignore files reading .ignore
, .gitignore
,
and .git/info/exclude
files in that order. If additional files need to be
ignored, it is also possible to add --exclude <glob>
to the call.
nixpkgs-fmt is available in nixpkgs master. nix-env -i nixpkgs-fmt
.
It's also possible to install it directly from this repository:
nix-env -f https://github.com/nix-community/nixpkgs-fmt/archive/master.tar.gz -i
This project can also be installed as a pre-commit hook.
Add to your project's .pre-commit-config.yaml
:
- repo: https://github.com/nix-community/nixpkgs-fmt
rev: master
hooks:
- id: nixpkgs-fmt
Make sure to have rust available in your environment.
Then run pre-commit install-hooks
Install Rust and Cargo or run nix-shell
to load the project dependencies.
Install pre-commit and run pre-commit install
to
setup the git hooks on the repository. This will allow to keep the code nicely
formatted over time.
Then use cargo run
to build and run the software.
$ cargo install cargo-fuzz
$ mkdir -p ./fuzz/corpus/fmt
$ cp test_data/**.nix ./fuzz/corpus/fmt
$ rustup run nightly -- cargo fuzz run fmt
or with nix:
$ nix-shell --run "cargo fuzz run fmt"
fmt
is the name of the target in ./fuzz/Cargo.toml
Fuzzer will run indefinitely or until it finds a crash.
The crashing input is written to fuzz/artifacts
directory.
Commit this crash-
file, and it will be automatically tested by a unit-test.
Feel free to submit your project!
rnix-lsp - A Lambda Server for Nix
This work has been sponsored by NumTide.