ormolu
ormolu copied to clipboard
Use .cabal or cabal.project to discover which files to format
Follow-up issue from https://github.com/fourmolu/fourmolu/issues/348.
It would be great if, instead of having to specify files to format via a directory or a complicated call to git
, ormolu
would simply detect the files to format in the same way cabal
does. Basically, if the command cabal build all --enable-tests --enable-benchmarks
would read a particular Haskell source file, then ormolu -i
should format that file.
Why the current situation is not good enough
For any particular project, I can somehow adapt the ormolu
call. But when I want to automatize (e.g. to write a good git
alias, or a github action), I want to be able to deal with any sort of Haskell project.
Specifying a directory
The docs recommend e.g. ormolu -i src
. This doesn't work for projects that have several folders (e.g. test
, benchmark
, app
) generically because a project might have any sort of folders. Also, it doesn't work when you have a cabal.project
structure.
git ls-files
The docs recommend ormolu --mode inplace $(git ls-files '*.hs')
, but this doesn't work in general because there might be other files like *.lhs
, *.md
. Also, it doesn't work if there is no git repository (e.g. downloading a tarball).
find
The docs recommend ormolu --mode inplace $(find . -name '*.hs')
, but this doesn't always work out of the box because there may be dist-newstyle
or other build folders which I don't want to format.
What would be the most straightforward way
Like cabal
, ormolu should automatically discover whether there is a *.cabal
file, and then format all of the Haskell source files specified in it, or if there is a cabal.project
file, format all the source files found from all the cabal projects in there. Advantages:
- Single point of definition what is part of the project and what is not
- No additional assumptions about directory structure or available tooling
Thanks, sounds interesting!
It is not immediately clear to me if there is a simple way to implement the cabal.project
-related logic, as that includes the overriding logic via cabal.project.local
as well as arbitrary imports (even from URLs!) since 3.8 (https://github.com/haskell/cabal/pull/7783). Ideally, Ormolu could somehow reuse that logic from Cabal, but I don't think that is possible ATM. We could choose to just not support that, but that would than violate your proposed slogan of "format a file if cabal build all --enable-tests --enable-benchmarks
reads it", and would then mean that it would be yet another "works most of the time" method, just as the existing ones you are listing in this issue. WDYT?
An alternative might be to allow to pass a list of .cabal
files to Ormolu, but then it is still the job of the user to construct that list, which maybe a bit easier than listing all Haskell source files, but that is not clear to me. :thinking:
The docs recommend
ormolu --mode inplace $(git ls-files '*.hs')
, but this doesn't work in general because there might be other files like*.lhs
,*.md
.
I am not sure what you are trying to say here: Ormolu can't format .lhs
or .md
files, and git ls-files '*.hs'
does not return such files, so what does not work?
My preferred way to list Haskell source files for e.g. Ormolu to format is via fd, i.e. fd -e hs
. It respects .gitignore
, but also works outside of Git repos. If that satsifies all your desiderata, we could add it to the README.
I think it'd be nice to also have the fd
example in the README, I've been using the git ls-files
command but fd
looks cleaner.
Ideally, Ormolu could somehow reuse that logic from Cabal, but I don't think that is possible ATM.
A heuristic would be to only use those *.cabal files that are both listed in cabal.project
and are in a subdirectory.
Ormolu can't format .lhs or .md files
Ah, I didn't know that! Nevermind then. I would have thought it could format literate Haskell, but I didn't research this.
fd
sounds like the best workaround so far. I still think that it is the wrong approach in principle. It might fail e.g. when I have an .hs
file that I didn't add to version control (e.g. a RandomNotes.hs
), it requires an extra external dependency (and thus extra installation steps, possible breakage, different CLI syntax, separate versions, harder to test for you, ...), it requires a command line with two steps.
Compare e.g. Rust with cargo fmt
. One command. You just run it. It does the expected thing. I'd prefer it to be that simple.
An alternative might be to allow to pass a list of .cabal files to Ormolu, but then it is still the job of the user to construct that list
If this is easy to implement then it may still be worth doing it, maybe new, simpler usage patterns will arise! I would definitely use such a feature.