On Nix Expression formatting


#1

I don’t really care about how code is indented that much, except for one instance. When brackets are unnecessarily placed on the same line as the items:

fileSystems."/nix" =
  { autoFormat = false;
    fsType = "ext4";
    device = "/dev/nvme1n1p1";
  };
}

So I am writing here to try to convince you that anything else is better than that :slight_smile:

This is fine:

fileSystems."/nix" = {

On it’s own line, it’s fine:

fileSystems."/nix" =
  {

Ok but why? you will ask.

  1. It takes more operations to sort lines
  2. It takes more operations when touching the first item of the attribute set
  3. Git diffs are unnecessarily larger
  4. It’s not necessary

This also goes for arrays. Nix is one of the very few languages where we don’t have to worry about commas between array entries. In any other language you have to choose between an ugly diff in front, or in the back of the array. But we don’t!

Bad format:

networking.firewall.allowedTCPPorts =
   [ 80
     443
     8080
   ];

Do you see the phantom commas?

Anyways, that’s about it. I understand that everyone has preferences and we have different language backgrounds. Some of these formats were influenced by the original language’s syntax restrictions and don’t have to apply in Nix.

:peace_symbol:


#2

Saving one line is the only motivation I can think of, i.e. not really convincing case. I agree with you, though I don’t mind that style so much; I’m not sure it’s worth to decide to convert all nixpkgs now :slight_smile: but perhaps per-file (or a larger section of it) when that file/section is significantly changed…


Some languages with commas allow trailing comma, i.e. you can write a comma after each element, even if it might be the last one. I do love that. AFAIK it’s similar with ; separating statements, only there the trailing ; is very often even required.


#3

Have not seen it much with lists or attrsets but it is quite common with functions:


{ stdenv

, foo

, bar

}:

...

There it allows aligning the items. I agree that it does not make much sense for the data structures.


#4

I don’t really care about how code is indented that much, except for one instance. When brackets are unnecessarily placed on the same line as the items:

fileSystems."/nix" =
  { autoFormat = false;
    fsType = "ext4";
    device = "/dev/nvme1n1p1";
  };
}

So I am writing here to try to convince you that anything else is better than that :slight_smile:

There is a single case where I’d not really be in agreement: lists of
relatively short sets:

someParameter = [
  { foo = bar;
    baz = quux;
  }
  { some = more;
    stuff = here;
  }
]

Here, I personally find this writing more readable than all other
alternatives I’ve seen up to now.

This has too much space separating the sets, making them look like they
belong to two different lists:

someParameter = [
  {
    foo = bar;
    baz = quux;
  }
  {
    some = more;
    stuff = here;
  }
]

This looks plain weird:

someParameter = [ {
    foo = bar;
    baz = quux;
  } {
    some = more;
    stuff = here;
} ];

And this too:

someParameter = [
  {
    foo = bar;
    baz = quux;
  } {
    some = more;
    stuff = here;
  }
];

Do you have a better idea for those lists-of-short-sets?


#5

We need a rule for 2D syntax :wink: (like e.g. Haskell or Python)


#6

I like your last example, it shows that there are multiple attrsets in that list without using too much whitespace, and at the same time it keeps git diffs minimal.

In any case, in several languages there’s a de-facto formatter: Javascript has Prettier, Go has gofmt etc.

It would be nice if we had a formatter for Nix…


#7

I would still use that form because it means that both items in the list and items in the attrsets can be moved around with minimal amount of work, in all editors. This encourages contributors of sorting things around in a way that makes sense. It also minimizes the merge conflicts. It’s not huge but I think it would make a difference over the size of nixpkgs.


#8

hnix contains a pretty-printer.


#9

yes please :slight_smile:


#10

It would be nice if we had a formatter for Nix…

I started work on nix-bikeshed [1] for this reason, that planned to
handle this (for the differences with a pretty-printer, see the
discussion at [2]). Unfortunately the work is currently blocked on [3]
being solved upstream at hnix, and I have too much stuff waiting
everywhere to take the time to try and handle this feature request
myself before I complete a few other projects…

[1] https://github.com/Ekleog/nix-bikeshed/

[2] https://github.com/haskell-nix/hnix/issues/57#issuecomment-435676100

[3] https://github.com/haskell-nix/hnix/issues/57


#11
$ ~/dev/hnix/result/bin/hnix foo.nix
{
  fileSystems."/nix" = {
    autoFormat = false;
    fsType = "ext4";
    device = "/dev/nvme1n1p1";
  };
}

Good, you had me worried for a second :slight_smile:


#12

That seems wrong – the code explicitly states autoFormat = false and it still got auto-formatted :roll_eyes:


#13

Ok, so the main thing blocking this right now is the lack of comment support in the AST? (And haskell closure size :stuck_out_tongue:)


#14

Just comment support, hnix can be compiled to ~10M musl executable without any dependencies.

Oh and performance https://github.com/haskell-nix/hnix/issues/200 - but we’re on it :slight_smile:


#15

I think we should update the nixpkgs style guide as well. It actually encourages exactly the list format several people here dislike most.

In my optimal world we would have core developers, the style guide and a source formatter in complete agreement.


#16

Thanks for pointing that out. Here you go: https://github.com/NixOS/nixpkgs/pull/51113