Skip to content

Commit

Permalink
Add option to respect default-extensions from .cabal files
Browse files Browse the repository at this point in the history
  • Loading branch information
amesgen authored and mrkkrp committed Aug 12, 2021
1 parent 3f52afa commit 4889228
Show file tree
Hide file tree
Showing 12 changed files with 279 additions and 698 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@
the native line ending conventions. [Issue
717](https://github.com/tweag/ormolu/issues/717).

* Opt-in support to respect default-extensions and default-language
from .cabal files. [Issue 517](https://github.com/tweag/ormolu/issues/517).

## Ormolu 0.2.0.0

* Now standalone kind signatures are grouped with type synonyms. [Issue
Expand Down
13 changes: 13 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
* [Editor integration](#editor-integration)
* [GitHub actions](#github-actions)
* [Magic comments](#magic-comments)
* [Account for .cabal files](#account-for-.cabal-files)
* [Exit codes](#exit-codes)
* [Limitations](#limitations)
* [Running on Hackage](#running-on-hackage)
Expand Down Expand Up @@ -163,6 +164,16 @@ source code must still be parseable even when the disabled regions are
omitted. Because of that the magic comments cannot be placed arbitrarily,
but rather must enclose independent top-level definitions.

### Account for .cabal files

Many cabal and stack projects use `default-extensions` to enable GHC
language extensions in all source files. With the
`--cabal-default-extensions` flag, Ormolu will take them into consideration
during formatting.

When you format input from stdin, you can pass `--stdin-input-file` which
will tell Ormolu to find and use a suitable .cabal file.

### Exit codes

Exit code | Meaning
Expand All @@ -175,6 +186,8 @@ Exit code | Meaning
5 | AST of original and formatted code differs
6 | Formatting is not idempotent
7 | Unrecognized GHC options
8 | Cabal file parsing failed
9 | Missing input file path when using stdin input and accounting for .cabal files
100 | In checking mode: unformatted files
101 | Inplace and check modes do not work with stdin
102 | Other issue (with multiple input files)
Expand Down
123 changes: 84 additions & 39 deletions app/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

module Main (main) where

import Control.Exception (throwIO)
import Control.Monad
import Data.Bool (bool)
import Data.List (intercalate, sort)
Expand All @@ -19,6 +20,7 @@ import Ormolu.Diff.Text (diffText, printTextDiff)
import Ormolu.Parser (manualExts)
import Ormolu.Terminal
import Ormolu.Utils (showOutputable)
import Ormolu.Utils.Extensions (getCabalExtensionDynOptions)
import Ormolu.Utils.IO
import Paths_ormolu (version)
import System.Exit (ExitCode (..), exitWith)
Expand All @@ -29,7 +31,7 @@ import System.IO (hPutStrLn, stderr)
main :: IO ()
main = do
Opts {..} <- execParser optsParserInfo
let formatOne' = formatOne optMode optConfig
let formatOne' = formatOne optCabalDefaultExtensions optMode optConfig
exitCode <- case optInputFiles of
[] -> formatOne' Nothing
["-"] -> formatOne' Nothing
Expand All @@ -52,50 +54,66 @@ main = do

-- | Format a single input.
formatOne ::
-- | Whether to respect default-extensions from .cabal files
CabalDefaultExtensionsOpts ->
-- | Mode of operation
Mode ->
-- | Configuration
Config RegionIndices ->
-- | File to format or stdin as 'Nothing'
Maybe FilePath ->
IO ExitCode
formatOne mode config mpath = withPrettyOrmoluExceptions (cfgColorMode config) $
case FP.normalise <$> mpath of
Nothing -> do
r <- ormoluStdin config
case mode of
Stdout -> do
TIO.putStr r
return ExitSuccess
_ -> do
hPutStrLn
stderr
"This feature is not supported when input comes from stdin."
-- 101 is different from all the other exit codes we already use.
return (ExitFailure 101)
Just inputFile -> do
originalInput <- readFileUtf8 inputFile
formattedInput <- ormoluFile config inputFile
case mode of
Stdout -> do
TIO.putStr formattedInput
return ExitSuccess
InPlace -> do
-- Only write when the contents have changed, in order to avoid
-- updating the modified timestamp if the file was already correctly
-- formatted.
when (formattedInput /= originalInput) $
writeFileUtf8 inputFile formattedInput
return ExitSuccess
Check ->
case diffText originalInput formattedInput inputFile of
Nothing -> return ExitSuccess
Just diff -> do
runTerm (printTextDiff diff) (cfgColorMode config) stderr
-- 100 is different to all the other exit code that are emitted
-- either from an 'OrmoluException' or from 'error' and
-- 'notImplemented'.
return (ExitFailure 100)
formatOne CabalDefaultExtensionsOpts {..} mode config mpath =
withPrettyOrmoluExceptions (cfgColorMode config) $
case FP.normalise <$> mpath of
Nothing -> do
extraDynOptions <-
if optUseCabalDefaultExtensions
then case optStdinInputFile of
Just stdinInputFile ->
getCabalExtensionDynOptions stdinInputFile
Nothing -> throwIO OrmoluMissingStdinInputFile
else pure []
r <- ormoluStdin (configPlus extraDynOptions)
case mode of
Stdout -> do
TIO.putStr r
return ExitSuccess
_ -> do
hPutStrLn
stderr
"This feature is not supported when input comes from stdin."
-- 101 is different from all the other exit codes we already use.
return (ExitFailure 101)
Just inputFile -> do
extraDynOptions <-
if optUseCabalDefaultExtensions
then getCabalExtensionDynOptions inputFile
else pure []
originalInput <- readFileUtf8 inputFile
formattedInput <- ormoluFile (configPlus extraDynOptions) inputFile
case mode of
Stdout -> do
TIO.putStr formattedInput
return ExitSuccess
InPlace -> do
-- Only write when the contents have changed, in order to avoid
-- updating the modified timestamp if the file was already correctly
-- formatted.
when (formattedInput /= originalInput) $
writeFileUtf8 inputFile formattedInput
return ExitSuccess
Check ->
case diffText originalInput formattedInput inputFile of
Nothing -> return ExitSuccess
Just diff -> do
runTerm (printTextDiff diff) (cfgColorMode config) stderr
-- 100 is different to all the other exit code that are emitted
-- either from an 'OrmoluException' or from 'error' and
-- 'notImplemented'.
return (ExitFailure 100)
where
configPlus dynOpts = config {cfgDynOptions = cfgDynOptions config ++ dynOpts}

----------------------------------------------------------------------------
-- Command line options parsing
Expand All @@ -106,7 +124,9 @@ data Opts = Opts
-- | Ormolu 'Config'
optConfig :: !(Config RegionIndices),
-- | Haskell source files to format or stdin (when the list is empty)
optInputFiles :: ![FilePath]
optInputFiles :: ![FilePath],
-- | Options for respecting default-extensions from .cabal files
optCabalDefaultExtensions :: CabalDefaultExtensionsOpts
}

-- | Mode of operation.
Expand All @@ -120,6 +140,17 @@ data Mode
Check
deriving (Eq, Show)

-- | Configuration for how to account for default-extension
-- from .cabal files
data CabalDefaultExtensionsOpts = CabalDefaultExtensionsOpts
{ -- | Account for default-extensions from .cabal files
optUseCabalDefaultExtensions :: Bool,
-- | Optional path to a file which will be used to
-- find a .cabal file when using input from stdin
optStdinInputFile :: Maybe FilePath
}
deriving (Show)

optsParserInfo :: ParserInfo Opts
optsParserInfo =
info (helper <*> ver <*> exts <*> optsParser) . mconcat $
Expand Down Expand Up @@ -171,6 +202,20 @@ optsParser =
[ metavar "FILE",
help "Haskell source files to format or stdin (the default)"
]
<*> cabalDefaultExtensionsParser

cabalDefaultExtensionsParser :: Parser CabalDefaultExtensionsOpts
cabalDefaultExtensionsParser =
CabalDefaultExtensionsOpts
<$> (switch . mconcat)
[ short 'e',
long "cabal-default-extensions",
help "Account for default-extensions from .cabal files"
]
<*> (optional . strOption . mconcat)
[ long "stdin-input-file",
help "Path which will be used to find the .cabal file when using input from stdin"
]

configParser :: Parser (Config RegionIndices)
configParser =
Expand Down
2 changes: 1 addition & 1 deletion default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ let
"ormolu" = super.callCabal2nixWithOptions "ormolu" source "-fdev" { };
"ghc-lib-parser" = self.ghc-lib-parser_9_0_1_20210324;
"path" = self.path_0_9_0;
"Cabal" = self.Cabal_3_4_0_0;
};
ormolize = import ./nix/ormolize {
inherit pkgs;
Expand All @@ -38,7 +39,6 @@ let
"pandoc"
"pipes"
"postgrest"
"purescript"
];
ormolizedPackages =
let
Expand Down
Loading

0 comments on commit 4889228

Please sign in to comment.