Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use .cabal or cabal.project to discover which files to format #1054

Open
turion opened this issue Jul 12, 2023 · 4 comments
Open

Use .cabal or cabal.project to discover which files to format #1054

turion opened this issue Jul 12, 2023 · 4 comments

Comments

@turion
Copy link

turion commented Jul 12, 2023

Follow-up issue from fourmolu/fourmolu#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
@amesgen
Copy link
Member

amesgen commented Jul 12, 2023

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 (haskell/cabal#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. 🤔


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.

@c0nradLC
Copy link

c0nradLC commented Nov 8, 2023

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.

@turion
Copy link
Author

turion commented Nov 8, 2023

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.

@turion
Copy link
Author

turion commented Nov 8, 2023

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants