Open m-renaud opened 5 years ago
@m-renaud see my comment on the other ticket. I think the amount of work here could profitably be put into resolving more issues with format
and won'tfix
was the wrong tag to give that ticket... I'd like to pursue further discussion there before continuing down this line.
@m-renaud very thoughtful proposal. I generally also love the idea to have the formatter for such purposes. But probably I would need more from that, like alphabetic order for build-depends or modules, base
/base-noprelude
always on the first place, etc., so I'm not sure if it fits well into cabal
itself, because the formatter either would have the large set of settings or it would be opinionated.
Details question: I don't really get why one could need redo
command, I guess, it's more intuitive for the user to run cabal fix
command again and this also won't let us format with a loss, for example, if the .cabal
file was change between undo
and redo
commands.
But overall I like the idea, and would be happy to see at least light version of it here.
I want to raise the attention for a recently released formatting tool ormolu
.
What cargo fmt
is for rust, could be cabal fmt
for Haskell.
The actual formatter rustfmt
could be ormolu
.
How can ormolu be integrated into cabal?
Identified requirements to date are:
cabal fmt
command, that calls ormolu
This is issue is about formatting .cabal files, not .hs sources.
My opinion is that ormolu
could depend on Cabal
the library to parse the .cabal
files, and then identify the sources (like sdist
command does, all of that is few dozens lines of code).
Or to say it directly: we won't hard code any formatters, why ormolu
and not say brittany
?
My opinion is that ormolu could depend on Cabal the library to parse the .cabal files, and then identify the sources (like sdist command does, all of that is few dozens lines of code).
Thanks for the idea!
My opinion is that ormolu could depend on Cabal the library to parse the .cabal files, and then identify the sources (like sdist command does, all of that is few dozens lines of code).
Ormolu is build-system independent. It depends on GHC but it won't depend on Cabal. There won't be anything that goes beyond single-file processing, in particular there won't be anything that will have anything to do with Cabal files (parsing them, etc.). It is outside of the scope of the tool.
Or to say it directly: we won't hard code any formatters, why ormolu and not say brittany?
Sure. The way to do is to have some sort of plugin system for this.
There's impedance mismatch in what tool writers want from build tools, e.g. hie-bios
would be happy with bare information how to construct ghci
command: or so I understood.
Please, if you want discuss Haskell code formatters, open a new issue. This issue is formatting *.cabal
files.
I'm locking the discussion until tomorrow.
Update
cabal check
to return different error code on parse failure vs. warning.
As now (b101f2d3d711a8532c54a0cf8ee1610683a30659), 1
exit is for “Hackage will refuse the package”. I will see if there is a way to accomodate a “parse error” indication.
`cabal check` exits with 0 or 1. As now the `1` exit is slightly
stricter than “Hackage would reject this”, as even PackageDistSuspicious
errors will trigger a `1` exit.
A useful and common (see for example grep(1)
) convention is that exit 1 is for primary failure (here, would be rejected by Hackage) and higher exits are for failures that prevent determination of the primary status (for grep
that means things like invalid regexes).
Overview
So, it became clear in #5734 that the purpose of
cabal format
is not, in fact, to format your cabal files, which I was sad to hear because I was looking for a tool to do that for a while. The main reason appears to be because it operates on aGenericPackageDescription
which doesn't maintain source file location (or things likecommon
stanzas).I propose that we create a
cabal fix
command with the following behaviour:Don't let great be the enemy of good
Yes, it would be possibly to build a full parser like exists for
GPD
, and also store source file locations, how things were populated, etc., but we could get a pretty long way with a much simpler and dumber formatter. Simple things like: remove trailing whitespace, always leave 1 space after the:
, two blank lines between stanzas, always hang "repeated fields" and put one per line (build-depends
,exposed-modules
, etc). Maybe it can't handle everything from the beginning, but if it can successfully format the majority of folks cabal files then I think that's a win.High Level Flow
cabal check
to return different error code on parse failure vs. warning.cabal fix
, which makes sure the file parses first (viacabal check
)Simplified Package Description
Since the majority of what we need to do doesn't care what an individual field or stanza represents, all we need to know is if the field is a single values field, a repeated field with optional commas, or a repeated field with required. This means we can use a much simpler package description and keep a list of which fields require different parsers/pretty printers. This should simplify the development greatly.
Support undo/redo
In case the formatter messes something up, there should be an easy way to revert it. One simple scheme is described below:
cabal fix --undo
This will replace cabal-file.cabal with
.cabal-fix/cabal-file.cabal.bak.n
and move the current cabal file to.cabal-fix/cabal-file.cabal.redo.n
cabal fix --redo
This will replace
cabal-file.cabal
with.cabal-fix/cabal-file.cabal.redo.n
Sample Formatted File
Prior Art
http://hackage.haskell.org/package/stylish-cabal (just found this, will check it out)
Edit: This looks like a good start, I'm personally not a fan of the indentation style, but I'll start by poking around in the code there and see what I can do.
Implementation
I've been looking for little side project to write in Haskell for a while so I'd be willing to implement this.
/cc @phadej @vrom911