Description
During this week's cabal maintainers call, the subject of contributors churn was raised, and an example that I noticed in some PRs was indentation. This is of course not a clear cut subject, because nobody wants to read weirdly-indented code but also we hate to manually indent stuff (especially on large patches), and personally I groan each time I get an entirely justified comment related to formatting.
I'd like to submit to the audience that we adopt a single formatting style of the codebase.
The tool is Fourmolu, a fork of Ormolu which integrates configuration flags, as opposed to the One True Style promoted by Ormolu.
Formolu comes with a GitHub Action, an interactive configuration visualiser.
One main reason that I'm suggesting Fourmolu is that we own the style. One very real criticism of late introduction of a formatter in a codebase is that we end up with a big commit that is just "format lol". Ormolu itself promotes a single style but this style evolves, and Fourmolu gives us the ability to disable the new additions to Ormolu. For me personally I would say it would remove quite a lot of frustration because I only want 1 reformatting commit and that's it.
In practice we can end up with conflicts between Ormolu and HLint: #1003 (Parentheses between some single class constraints conflict with hlint rules), which is why I'm in favour of actively owning our style, yet be able to automatically enforce it rather than spend time and energy doing it manually.
Moreover, Fourmolu options reduce diffs, which is a net benefit when reviewing PRs.
Here what it could look like:
diff --git a/Lol.hs b/Lol.hs
index 83772f1..dec18b5 100644
--- a/Lol.hs
+++ b/Lol.hs
@@ -1,16 +1,25 @@
-build :: PackageDescription -- ^ Mostly information from the .cabal file
- -> LocalBuildInfo -- ^ Configuration information
- -> BuildFlags -- ^ Flags that the user passed to build
- -> [ PPSuffixHandler ] -- ^ preprocessors to run before compiling
- -> IO ()
+build
+ :: PackageDescription
+ -- ^ Mostly information from the .cabal file
+ -> LocalBuildInfo
+ -- ^ Configuration information
+ -> BuildFlags
+ -- ^ Flags that the user passed to build
+ -> [PPSuffixHandler]
+ -- ^ preprocessors to run before compiling
+ -> IO ()
build pkg_descr lbi flags suffixes = do
checkBuildProblems verbosity (compiler lbi) flags
targets <- readTargetInfos verbosity pkg_descr lbi (buildArgs flags)
let componentsToBuild = neededTargetsInBuildOrder' pkg_descr lbi (map nodeKey targets)
- info verbosity $ "Component build order: "
- ++ intercalate ", "
- (map (showComponentName . componentLocalName . targetCLBI)
- componentsToBuild)
+ info verbosity $
+ "Component build order: "
+ ++ intercalate
+ ", "
+ ( map
+ (showComponentName . componentLocalName . targetCLBI)
+ componentsToBuild
+ )
when (null targets) $
-- Only bother with this message if we're building the whole package
setupMessage verbosity "Building" (packageId pkg_descr)
@@ -24,26 +33,28 @@ build pkg_descr lbi flags suffixes = do
let comp = targetComponent target
clbi = targetCLBI target
componentInitialBuildSteps distPref pkg_descr lbi clbi verbosity
- let bi = componentBuildInfo comp
+ let bi = componentBuildInfo comp
progs' = addInternalBuildTools pkg_descr lbi bi (withPrograms lbi)
- lbi' = lbi {
- withPrograms = progs',
- withPackageDB = withPackageDB lbi ++ [internalPackageDB],
- installedPkgs = index
- }
+ lbi' =
+ lbi
+ { withPrograms = progs'
+ , withPackageDB = withPackageDB lbi ++ [internalPackageDB]
+ , installedPkgs = index
+ }
mb_ipi <- buildComponent verbosity (buildNumJobs flags) pkg_descr
- par_strat <- toFlag <$> case buildUseSemaphore flags of
- Flag sem_name -> case buildNumJobs flags of
- Flag {} -> do
- warn verbosity $ "Ignoring -j due to -semaphore"
- return $ UseSem sem_name
- NoFlag -> return $ UseSem sem_name
- NoFlag -> return $ case buildNumJobs flags of
- Flag n -> NumJobs n
- NoFlag -> Serial
+ par_strat <-
+ toFlag <$> case buildUseSemaphore flags of
+ Flag sem_name -> case buildNumJobs flags of
+ Flag{} -> do
+ warn verbosity $ "Ignoring -j due to -semaphore"
+ return $ UseSem sem_name
+ NoFlag -> return $ UseSem sem_name
+ NoFlag -> return $ case buildNumJobs flags of
+ Flag n -> NumJobs n
+ NoFlag -> Serial
return (maybe index (Index.insert `flip` index) mb_ipi)
-
+
return ()
- where
- distPref = fromFlag (buildDistPref flags)
- verbosity = fromFlag (buildVerbosity flags)
+ where
+ distPref = fromFlag (buildDistPref flags)
+ verbosity = fromFlag (buildVerbosity flags)
Personally I believe that the combo of normalisation, automation and ownership of the coding style is something that could remove a certain burden from our contributors and reviewers.
PS: Of course I would provide the initial CI setup and reformatting PR.