haskell / cabal

Official upstream development repository for Cabal and cabal-install
https://haskell.org/cabal
Other
1.61k stars 691 forks source link

Create cabal-fmt, a style enforcer for .cabal and .config files #1504

Open tibbe opened 11 years ago

tibbe commented 11 years ago

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 support install --freeze-dependencies. Briefly, that command would edit the constraints section of the cabal.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 and init and e.g. emacs-mode could use it as a on-save hook for .cabal files.

byorgey commented 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.

tibbe commented 11 years ago

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.

dcoutts commented 11 years ago

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.

tibbe commented 11 years ago

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.

23Skidoo commented 10 years ago

@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

seagreen commented 8 years ago

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).