Open tibbe opened 11 years ago
This is a great idea. I note that this would also have benefits for cabal init
--- several people have suggested turning cabal init
into a more general tool for automatically updating one's .cabal
file instead of just generating an initial one, but that proposal has been stalled precisely because of this problem of needing to preserve formatting.
So here's a strawman proposal for the style: we don't do any fancy aligning. Example:
Library
Exposed-modules:
Data.Hashable
Other-modules:
Data.Hashable.Class
Build-depends:
base >= 4.0 && < 5.0,
bytestring >= 0.9
if impl(ghc)
Build-depends:
ghc-prim,
text >= 0.11.0.5
if impl(ghc) && flag(integer-gmp)
Build-depends:
integer-gmp >= 0.2
if impl(ghc >= 7.2.1)
CPP-Options: -DGENERICS
Other-modules:
Data.Hashable.Generic
C-sources:
cbits/fnv.c
Ghc-options: -Wall
if impl(ghc >= 6.8)
Ghc-options: -fwarn-tabs
if flag(fixed-salt)
Cpp-options: -DFIXED_SALT
else
c-sources:
cbits/getRandomBytes.c
other-modules:
Data.Hashable.RandomSource
if os(windows)
extra-libraries: advapi32
Repeated sections (e.g. build-depends
, other-modules
) just list the fields below, indented 2 spaces. We agree on some ordering of the sections. We decide whether we use title-case or lower-case for section names.
I've been thinking of a similar idea, about rewriting cabal style files (.cabal and config files). But instead of pretty-printing in a standard way and throwing way comments, trying to preserve all the original layout etc.
However this work is stalled on the new parser that I have written, which is stalled on the fact that I want to use parsec, and this extra dependency is a problem for ghc at the moment. We might get some movement on that as ghc wants to reduce its dependency on Cabal, so it may become easier to add the parsec dependency.
I don't think you can get away with not having some style rules in your pretty-printer, even if it preserves the whole concrete syntax. Consider this input:
-- 80 line long comment
foo-section: bar
that we want to programmatically wrap in an if:
if flag:
-- 80 line long comment
foo-section: bar
While you might have preserved the user's formatting/comment, you haven't preserved the intention (80 column wrapping). I believe this is why Go does what it does. Once you start actually rewriting the code, it's no longer clear what to do without style rules.
@tibbe wrote a bit more about this on his blog: http://blog.johantibell.com/2014/03/google-summer-of-code-projects.html#cabal-file-pretty-printer
This is a great idea, and I'm also fine with no fancy aligning (in fact I think that's better since it will make git diffs cleaner).
This idea is a bit more "out there".
We'd like to do some automatic rewriting of user edited files, namely
cabal.config
, in order to supportinstall --freeze-dependencies
. Briefly, that command would edit theconstraints
section of thecabal.config
file.Since the user also edits
cabal.config
we have the problem of automatically editing the file without introducing spurious changes e.g. whitespace-changes or section ordering changes.The Go programming language tackles this problem in the area of source code by simply requiring all source code to be formatted the same way, using the go-fmt tool to enforce this. This makes automatic rewriting much easier, as you can do the rewriting in any which way and run the result through go-fmt.
The idea would be to decide on a style for .cabal and .config files and have a tool that can be used to enforce it. I hope such a style shouldn't be too controversial as there's very little meaningful formatting to be done in these two file types.
Once we have this tool cabal itself can use it in both
install --freeze-dependencies
andinit
and e.g. emacs-mode could use it as a on-save hook for .cabal files.