{-# LANGUAGE Rank2Types #-} module Main ( main ) where import Actions import ExitCode import Language.Haskell.Format import Language.Haskell.Format.Utilities import Language.Haskell.Source.Enumerator import Options import Types import Conduit import Options.Applicative.Extra as OptApp import System.Directory import System.Exit import System.IO main :: IO () main = do options <- execParser Options.parser result <- run options exitWith $ exitCode (optAction options) result run :: Options -> IO RunResult run opt = runConduit $ sources opt .| mapMC readSource .| mapMC formatSource .| mapMC doAction .| foldMapMC toRunResult where formatSource source = do formatter <- defaultFormatter return $ applyFormatter formatter source doAction :: FormatResult -> IO FormatResult doAction = bimapM return (Actions.act opt) toRunResult :: FormatResult -> IO RunResult toRunResult (Left err) = do hPrint stderr (show err) return SourceParseFailure toRunResult (Right (Formatted _ source result)) = if wasReformatted source result then return HadDifferences else return NoDifferences sources :: Options -> ConduitT () SourceFile IO () sources opt = lift paths >>= mapM_ sourcesFromPath where explicitPaths = optPaths opt paths = if null explicitPaths then do currentPath <- getCurrentDirectory return [currentPath] else return explicitPaths sourcesFromPath :: FilePath -> ConduitT () SourceFile IO () sourcesFromPath "-" = yield StdinSource sourcesFromPath path = enumeratePath path .| mapC SourceFilePath readSource :: SourceFile -> IO SourceFileWithContents readSource s@(SourceFilePath path) = SourceFileWithContents s . HaskellSource path <$> readFile path readSource s@StdinSource = SourceFileWithContents s . HaskellSource "stdin" <$> getContents applyFormatter :: Formatter -> SourceFileWithContents -> FormatResult applyFormatter (Formatter doFormat) (SourceFileWithContents file contents) = case doFormat contents of Left err -> Left (FormatError file err) Right reformat -> Right (Formatted file contents reformat) bimapM :: Monad m => (a -> m c) -> (b -> m d) -> Either a b -> m (Either c d) bimapM f _ (Left a) = Left <$> f a bimapM _ g (Right b) = Right <$> g b