hfmt 0.0.2.3 → 0.1.0
raw patch · 17 files changed
+346/−177 lines, 17 filesdep +bytestringdep +exceptionsdep +pathdep ~hindentdep ~hlintdep ~stylish-haskellPVP ok
version bump matches the API change (PVP)
Dependencies added: bytestring, exceptions, path, path-io, transformers, yaml
Dependency ranges changed: hindent, hlint, stylish-haskell
API changes (from Hackage documentation)
- Language.Haskell.Format: data Formatter
+ Language.Haskell.Format: newtype Formatter
Files
- README.md +2/−2
- app/Actions.hs +7/−3
- app/Main.hs +14/−6
- app/OptionsParser.hs +51/−43
- app/Types.hs +27/−19
- hfmt.cabal +11/−4
- src/Language/Haskell/Format.hs +15/−14
- src/Language/Haskell/Format/Definitions.hs +24/−9
- src/Language/Haskell/Format/HIndent.hs +52/−14
- src/Language/Haskell/Format/HLint.hs +22/−26
- src/Language/Haskell/Format/Internal.hs +4/−1
- src/Language/Haskell/Format/Stylish.hs +10/−4
- src/Language/Haskell/Format/Utilities.hs +28/−19
- src/Language/Haskell/Source/Enumerator.hs +15/−7
- src/Path/Find.hs +52/−0
- test/pure/Spec.hs +3/−1
- test/self-formatting/Spec.hs +9/−5
README.md view
@@ -12,11 +12,11 @@ with [stack](https://www.haskellstack.org/) - $ cabal install hfmt+ $ stack install hfmt with [cabal](https://www.haskell.org/haskellwiki/Cabal/How_to_install_a_Cabal_package) - $ stack install hfmt+ $ cabal install hfmt ## Usage
app/Actions.hs view
@@ -1,4 +1,6 @@-module Actions (act) where+module Actions+ ( act+ ) where import Language.Haskell.Format import OptionsParser@@ -16,7 +18,8 @@ return r act options r@(Reformat input source result) = act' (optAction options) where- act' PrintDiffs = when wasReformatted (printDiff input source result) >> return r+ act' PrintDiffs =+ when wasReformatted (printDiff input source result) >> return r act' PrintSources = undefined act' PrintFilePaths = when wasReformatted (print input) >> return r act' WriteSources = do@@ -26,7 +29,8 @@ sourceChangedOrHasSuggestions :: HaskellSource -> Reformatted -> Bool sourceChangedOrHasSuggestions source reformatted =- not (null (suggestions reformatted)) || source /= reformattedSource reformatted+ not (null (suggestions reformatted)) ||+ source /= reformattedSource reformatted printDiff :: InputFile -> HaskellSource -> Reformatted -> IO () printDiff (InputFilePath path) source reformatted = do
app/Main.hs view
@@ -1,4 +1,6 @@-module Main (main) where+module Main+ ( main+ ) where import Actions import Language.Haskell.Format@@ -28,7 +30,9 @@ runFormatter :: Formatter -> Options -> IO Bool runFormatter formatter options =- anyStrict sourceChangedOrHasSuggestions (inputFiles >-> P.map reformat >-> P.mapM writeOutput)+ anyStrict+ sourceChangedOrHasSuggestions+ (inputFiles >-> P.map reformat >-> P.mapM writeOutput) where anyStrict :: Monad m => (a -> Bool) -> Producer a m () -> m Bool anyStrict f = P.fold (\acc x -> acc || f x) False id@@ -37,15 +41,18 @@ writeOutput = Actions.act options readInputFiles :: Options -> Producer InputFileWithSource IO ()-readInputFiles options = determineInputFilePaths (optPaths options) >-> P.mapM readInputFile+readInputFiles options =+ determineInputFilePaths (optPaths options) >-> P.mapM readInputFile determineInputFilePaths :: [FilePath] -> Producer InputFile IO () determineInputFilePaths [] = enumeratePath "." >-> P.map InputFilePath determineInputFilePaths ["-"] = yield InputFromStdIn-determineInputFilePaths paths = for (each paths) enumeratePath >-> P.map InputFilePath+determineInputFilePaths paths =+ for (each paths) enumeratePath >-> P.map InputFilePath readInputFile :: InputFile -> IO InputFileWithSource-readInputFile (InputFilePath path) = InputFileWithSource (InputFilePath path) <$> readSource path+readInputFile (InputFilePath path) =+ InputFileWithSource (InputFilePath path) <$> readSource path readInputFile InputFromStdIn = InputFileWithSource InputFromStdIn <$> readStdin applyFormatter :: Formatter -> InputFileWithSource -> ReformatResult@@ -62,4 +69,5 @@ sourceChangedOrHasSuggestions :: ReformatResult -> Bool sourceChangedOrHasSuggestions (Reformat input source reformatted) =- not (null (suggestions reformatted)) || source /= reformattedSource reformatted+ not (null (suggestions reformatted)) ||+ source /= reformattedSource reformatted
app/OptionsParser.hs view
@@ -1,4 +1,9 @@-module OptionsParser (Options, optAction, optPaths, parser) where+module OptionsParser+ ( Options+ , optAction+ , optPaths+ , parser+ ) where import Types @@ -10,14 +15,13 @@ import Options.Applicative.Extra import Text.PrettyPrint.ANSI.Leijen hiding (empty, (<$>), (<>)) -data Options =- Options- { optPrintDiffs :: Bool- , optPrintSources :: Bool- , optPrintFilePaths :: Bool- , optWriteSources :: Bool- , optPaths :: [FilePath]- }+data Options = Options+ { optPrintDiffs :: Bool+ , optPrintSources :: Bool+ , optPrintFilePaths :: Bool+ , optWriteSources :: Bool+ , optPaths :: [FilePath]+ } optAction :: Options -> Action optAction options@@ -29,49 +33,53 @@ | otherwise = PrintDiffs optionParser :: Parser Options-optionParser = Options <$> switch- (long "print-diffs" <>- short 'd' <>- help "If a file's formatting is different, print a diff.")- <*> switch- (long "print-sources" <>- short 's' <>- help "If a file's formatting is different, print its source.")- <*> switch- (long "print-paths" <>- short 'l' <>- help "If a file's formatting is different, print its path.")- <*> switch- (long "write-sources" <>- short 'w' <>- help "If a file's formatting is different, overwrite it.")- <*> many pathOption+optionParser =+ Options <$>+ switch+ (long "print-diffs" <> short 'd' <>+ help "If a file's formatting is different, print a diff.") <*>+ switch+ (long "print-sources" <> short 's' <>+ help "If a file's formatting is different, print its source.") <*>+ switch+ (long "print-paths" <> short 'l' <>+ help "If a file's formatting is different, print its path.") <*>+ switch+ (long "write-sources" <> short 'w' <>+ help "If a file's formatting is different, overwrite it.") <*>+ many pathOption where pathOption = strArgument (metavar "PATH" <> pathOptionHelp)- pathOptionHelp = helpDoc $ Just $- paragraph "Explicit paths to process." <> hardline- <> unorderdedList " - "- [ paragraph "A single '-' will process standard input."- , paragraph "Files will be processed directly."- , paragraph "Directories will be recursively searched for source files to process."- , paragraph- ".cabal files will be parsed and all specified source directories and files processed."- , paragraph- "If no paths are given, the current directory will be searched for .cabal files to process, if none are found the current directory will be recursively searched for source files to process."- ]+ pathOptionHelp =+ helpDoc $+ Just $+ paragraph "Explicit paths to process." <> hardline <>+ unorderdedList+ " - "+ [ paragraph "A single '-' will process standard input."+ , paragraph "Files will be processed directly."+ , paragraph+ "Directories will be recursively searched for source files to process."+ , paragraph+ ".cabal files will be parsed and all specified source directories and files processed."+ , paragraph+ "If no paths are given, the current directory will be searched for .cabal files to process, if none are found the current directory will be recursively searched for source files to process."+ ] paragraph :: String -> Doc paragraph = mconcat . intersperse softline . map text . words unorderdedList :: String -> [Doc] -> Doc-unorderdedList prefix = encloseSep (text prefix) mempty (text prefix) . map (hang 0)+unorderdedList prefix =+ encloseSep (text prefix) mempty (text prefix) . map (hang 0) optionParserInfo :: ParserInfo Options-optionParserInfo = info (helper <*> optionParser)- (fullDesc- <> header "hfmt - format Haskell programs"- <> progDesc- "Operates on Haskell source files, reformatting them by applying suggestions from HLint, hindent, and stylish-haskell. Inspired by the gofmt utility.")+optionParserInfo =+ info+ (helper <*> optionParser)+ (fullDesc <> header "hfmt - format Haskell programs" <>+ progDesc+ "Operates on Haskell source files, reformatting them by applying suggestions from HLint, hindent, and stylish-haskell. Inspired by the gofmt utility.") parser :: ParserInfo Options parser = optionParserInfo
app/Types.hs view
@@ -1,31 +1,39 @@-module Types (- Action(..),- InputFile(..),- InputFileWithSource(..),- ErrorString,- ReformatResult(..),- HaskellSourceFilePath,- HaskellSource(..),- ) where+module Types+ ( Action(..)+ , InputFile(..)+ , InputFileWithSource(..)+ , ErrorString+ , ReformatResult(..)+ , HaskellSourceFilePath+ , HaskellSource(..)+ ) where import Language.Haskell.Format import Language.Haskell.Source.Enumerator (HaskellSourceFilePath) -data Action = PrintDiffs- | PrintSources- | PrintFilePaths- | WriteSources+data Action+ = PrintDiffs+ | PrintSources+ | PrintFilePaths+ | WriteSources -data InputFile = InputFilePath HaskellSourceFilePath- | InputFromStdIn+data InputFile+ = InputFilePath HaskellSourceFilePath+ | InputFromStdIn instance Show InputFile where show (InputFilePath path) = path- show InputFromStdIn = "-"+ show InputFromStdIn = "-" -data InputFileWithSource = InputFileWithSource InputFile HaskellSource+data InputFileWithSource =+ InputFileWithSource InputFile+ HaskellSource type ErrorString = String -data ReformatResult = InvalidReformat InputFile ErrorString- | Reformat InputFile HaskellSource Reformatted+data ReformatResult+ = InvalidReformat InputFile+ ErrorString+ | Reformat InputFile+ HaskellSource+ Reformatted
hfmt.cabal view
@@ -1,5 +1,5 @@ name: hfmt-version: 0.0.2.3+version: 0.1.0 synopsis: Haskell source code formatter description: Inspired by gofmt. Built using hlint, hindent, and stylish-haskell. license: MIT@@ -25,18 +25,25 @@ , Language.Haskell.Format.HIndent , Language.Haskell.Format.HLint , Language.Haskell.Format.Stylish+ , Path.Find GHC-Options: -Wall Build-Depends: base >= 4.8 && < 5+ , bytestring , Cabal , directory+ , exceptions , filepath , haskell-src-exts- , hindent >= 4.5 , hindent < 5- , hlint >= 1.9.13 , hlint < 2+ , hindent >= 5.0.0+ , hlint >= 1.9 , HUnit+ , path+ , path-io , pipes- , stylish-haskell >= 0.5 , stylish-haskell < 0.6+ , stylish-haskell >= 0.7 , text+ , transformers+ , yaml executable hfmt Hs-Source-Dirs: app
src/Language/Haskell/Format.hs view
@@ -1,16 +1,16 @@-module Language.Haskell.Format (- autoSettings,- format,- formatters,- hlint,- hindent,- stylish,- Settings,- Formatter(..),- Suggestion(..),- HaskellSource(..),- Reformatted(..),- ) where+module Language.Haskell.Format+ ( autoSettings+ , format+ , formatters+ , hlint+ , hindent+ , stylish+ , Settings+ , Formatter(..)+ , Suggestion(..)+ , HaskellSource(..)+ , Reformatted(..)+ ) where import Language.Haskell.Format.Definitions import qualified Language.Haskell.Format.HIndent as HIndent@@ -20,7 +20,8 @@ import Control.Applicative import Data.Maybe -data Settings = Settings+data Settings =+ Settings autoSettings :: IO Settings autoSettings = return Settings
src/Language/Haskell/Format/Definitions.hs view
@@ -1,4 +1,9 @@-module Language.Haskell.Format.Definitions (HaskellSource(..), Reformatted(..), Formatter(..), Suggestion(..)) where+module Language.Haskell.Format.Definitions+ ( HaskellSource(..)+ , Reformatted(..)+ , Formatter(..)+ , Suggestion(..)+ ) where import Control.Applicative import Control.Monad@@ -6,26 +11,36 @@ type ErrorString = String -newtype HaskellSource = HaskellSource String- deriving Eq+newtype HaskellSource =+ HaskellSource String+ deriving (Eq) -newtype Suggestion = Suggestion String+newtype Suggestion =+ Suggestion String instance Show Suggestion where show (Suggestion text) = text -data Reformatted = Reformatted { reformattedSource :: HaskellSource, suggestions :: [Suggestion] }+data Reformatted = Reformatted+ { reformattedSource :: HaskellSource+ , suggestions :: [Suggestion]+ } instance Monoid Reformatted where mempty = Reformatted undefined []- (Reformatted _ suggestionsA) `mappend` (Reformatted sourceB suggestionsB) = Reformatted sourceB- (suggestionsA <> suggestionsB)+ (Reformatted _ suggestionsA) `mappend` (Reformatted sourceB suggestionsB) =+ Reformatted sourceB (suggestionsA <> suggestionsB) -data Formatter = Formatter { unFormatter :: HaskellSource -> Either ErrorString Reformatted }+newtype Formatter = Formatter+ { unFormatter :: HaskellSource -> Either ErrorString Reformatted+ } instance Monoid Formatter where mempty = Formatter (\source -> Right (Reformatted source [])) (Formatter f) `mappend` (Formatter g) = Formatter (asReformatter g <=< f) -asReformatter :: (HaskellSource -> Either ErrorString Reformatted) -> Reformatted -> Either ErrorString Reformatted+asReformatter ::+ (HaskellSource -> Either ErrorString Reformatted)+ -> Reformatted+ -> Either ErrorString Reformatted asReformatter formatter r = (r <>) <$> formatter (reformattedSource r)
src/Language/Haskell/Format/HIndent.hs view
@@ -1,28 +1,66 @@-module Language.Haskell.Format.HIndent (autoSettings, formatter, defaultFormatter) where+module Language.Haskell.Format.HIndent+ ( autoSettings+ , formatter+ , defaultFormatter+ ) where -import Control.Applicative-import Data.Maybe-import Data.Text.Lazy as L-import Data.Text.Lazy.Builder-import HIndent-import Language.Haskell.Exts.Extension (Extension)+import Control.Applicative+import Data.ByteString.Builder+import Data.ByteString.Lazy as L+import Data.Maybe+import qualified Data.Text as Text+import Data.Text.Encoding as Encoding+import Data.Text.Lazy as TL+import Data.Text.Lazy.Builder+import qualified Data.Yaml as Y+import HIndent+import HIndent.Types+import Language.Haskell.Exts.Extension (Extension)+import Path+import qualified Path.Find as Path+import qualified Path.IO as Path -import Language.Haskell.Format.Definitions-import Language.Haskell.Format.Internal+import Language.Haskell.Format.Definitions+import Language.Haskell.Format.Internal -data Settings = Settings Style (Maybe [Extension])+data Settings =+ Settings Config+ (Maybe [Extension]) defaultFormatter :: IO Formatter defaultFormatter = formatter <$> autoSettings autoSettings :: IO Settings-autoSettings = return (Settings gibiansky Nothing)+autoSettings = do+ config <- getConfig+ return (Settings config Nothing) +-- | Read config from a config file, or return 'defaultConfig'.+getConfig :: IO Config+getConfig = do+ cur <- Path.getCurrentDir+ homeDir <- Path.getHomeDir+ mfile <-+ Path.findFileUp+ cur+ ((== ".hindent.yaml") . toFilePath . filename)+ (Just homeDir)+ case mfile of+ Nothing -> return defaultConfig+ Just file -> do+ result <- Y.decodeFileEither (toFilePath file)+ case result of+ Left e -> error (show e)+ Right config -> return config+ formatter :: Settings -> Formatter formatter = mkFormatter . hindent hindent :: Settings -> HaskellSource -> Either String HaskellSource-hindent (Settings style extensions) (HaskellSource source) =- HaskellSource . L.unpack . toLazyText <$> reformat style extensions sourceText+hindent (Settings config extensions) (HaskellSource source) =+ toHaskellSource <$> reformat config extensions Nothing sourceText where- sourceText = L.pack source+ sourceText = Encoding.encodeUtf8 . Text.pack $ source+ toHaskellSource =+ HaskellSource .+ Text.unpack . Encoding.decodeUtf8 . L.toStrict . toLazyByteString
src/Language/Haskell/Format/HLint.hs view
@@ -1,40 +1,36 @@-module Language.Haskell.Format.HLint (autoSettings, formatter, suggester) where+module Language.Haskell.Format.HLint+ ( autoSettings+ , suggester+ ) where import Language.Haskell.Format.Definitions import Language.Haskell.Format.Internal import Control.Applicative-import Language.Haskell.Exts.Annotated as Hse+import Language.Haskell.HLint3 (Classify, Hint,+ ParseError (..),+ ParseFlags, applyHints,+ parseModuleEx) import qualified Language.Haskell.HLint3 as HLint3--formatter = undefined+import System.IO.Unsafe (unsafePerformIO) -suggester :: (ParseMode, [HLint3.Classify], HLint3.Hint) -> Formatter+suggester :: (ParseFlags, [Classify], Hint) -> Formatter suggester = mkSuggester . hlint -hlint :: (ParseMode, [HLint3.Classify], HLint3.Hint) -> HaskellSource -> Either String [Suggestion]-hlint (parseMode, classifications, hint) (HaskellSource source) =- getSuggestions <$> parseResultAsEither (parse source)+hlint ::+ (ParseFlags, [Classify], Hint)+ -> HaskellSource+ -> Either String [Suggestion]+hlint (flags, classify, hint) (HaskellSource source) =+ case unsafePerformIO (parseModuleEx flags filepath (Just source)) of+ Right m -> Right . map ideaToSuggestion . ideas $ m+ Left parseError -> Left . parseErrorMessage $ parseError where- parse = Hse.parseFileContentsWithComments parseMode- getSuggestions moduleSource = map ideaToSuggestion $ HLint3.applyHints classifications hint- [moduleSource]--autoSettings :: IO (ParseMode, [HLint3.Classify], HLint3.Hint)-autoSettings = do- (fixities, classify, hints) <- HLint3.findSettings (HLint3.readSettingsFile Nothing) Nothing- return- (HLint3.hseFlags (HLint3.parseFlagsAddFixities fixities HLint3.defaultParseFlags), classify, HLint3.resolveHints- hints)+ filepath = ""+ ideas m = applyHints classify hint [m] -parseResultAsEither :: ParseResult a -> Either String a-parseResultAsEither (ParseOk a) = Right a-parseResultAsEither (ParseFailed loc error) =- Left ("Parse failed at " ++ location ++ ": " ++ error)- where- location = filename ++ " " ++ linecol- filename = "[" ++ srcFilename loc ++ "]"- linecol = "(" ++ show (srcLine loc) ++ ":" ++ show (srcColumn loc) ++ ")"+autoSettings :: IO (ParseFlags, [Classify], Hint)+autoSettings = HLint3.autoSettings ideaToSuggestion :: HLint3.Idea -> Suggestion ideaToSuggestion = Suggestion . show
src/Language/Haskell/Format/Internal.hs view
@@ -1,4 +1,7 @@-module Language.Haskell.Format.Internal (mkFormatter, mkSuggester) where+module Language.Haskell.Format.Internal+ ( mkFormatter+ , mkSuggester+ ) where import Language.Haskell.Format.Definitions
src/Language/Haskell/Format/Stylish.hs view
@@ -1,4 +1,7 @@-module Language.Haskell.Format.Stylish (autoSettings, formatter) where+module Language.Haskell.Format.Stylish+ ( autoSettings+ , formatter+ ) where import Control.Applicative import Language.Haskell.Stylish as Stylish@@ -6,17 +9,20 @@ import Language.Haskell.Format.Definitions import Language.Haskell.Format.Internal -data Settings = Settings Stylish.Config+newtype Settings =+ Settings Stylish.Config autoSettings :: IO Settings-autoSettings = Settings <$> Stylish.loadConfig (Stylish.makeVerbose False) Nothing+autoSettings =+ Settings <$> Stylish.loadConfig (Stylish.makeVerbose False) Nothing formatter :: Settings -> Formatter formatter = mkFormatter . stylish stylish :: Settings -> HaskellSource -> Either String HaskellSource stylish (Settings config) (HaskellSource source) =- HaskellSource . unlines <$> Stylish.runSteps extensions Nothing steps sourceLines+ HaskellSource . unlines <$>+ Stylish.runSteps extensions Nothing steps sourceLines where sourceLines = lines source extensions = Stylish.configLanguageExtensions config
src/Language/Haskell/Format/Utilities.hs view
@@ -1,4 +1,8 @@-module Language.Haskell.Format.Utilities (wasReformatted, hunitTest, defaultFormatter) where+module Language.Haskell.Format.Utilities+ ( wasReformatted+ , hunitTest+ , defaultFormatter+ ) where import Language.Haskell.Format import Language.Haskell.Format.Definitions@@ -13,32 +17,36 @@ type ErrorString = String -data CheckResult = InvalidCheckResult ErrorString- | CheckResult HaskellSource Reformatted+data CheckResult+ = InvalidCheckResult ErrorString+ | CheckResult HaskellSource+ Reformatted hunitTest :: FilePath -> Test hunitTest filepath = TestLabel filepath $ makeTestCase filepath makeTestCase :: FilePath -> Test-makeTestCase filepath = TestCase $ do- formatter <- defaultFormatter- runEffect $ check formatter filepath >-> assertResults+makeTestCase filepath =+ TestCase $ do+ formatter <- defaultFormatter+ runEffect $ check formatter filepath >-> assertResults assertResults :: Consumer CheckResult IO ()-assertResults = forever $ do- result <- await- case result of- (InvalidCheckResult errorString) -> lift $ assertFailure ("Error: " ++ errorString)- (CheckResult source reformatted) -> when (wasReformatted source reformatted) $ lift $ assertFailure- ("Incorrect formatting: " ++ concatMap- show- (suggestions- reformatted))+assertResults =+ forever $ do+ result <- await+ case result of+ (InvalidCheckResult errorString) ->+ lift $ assertFailure ("Error: " ++ errorString)+ (CheckResult source reformatted) ->+ when (wasReformatted source reformatted) $+ lift $+ assertFailure+ ("Incorrect formatting: " ++ concatMap show (suggestions reformatted)) check :: Formatter -> FilePath -> Producer CheckResult IO ()-check formatter path = enumeratePath path >->- P.mapM readSource >->- P.map (checkFormatting formatter)+check formatter path =+ enumeratePath path >-> P.mapM readSource >-> P.map (checkFormatting formatter) readSource :: HaskellSourceFilePath -> IO HaskellSource readSource path = HaskellSource <$> readFile path@@ -57,4 +65,5 @@ wasReformatted :: HaskellSource -> Reformatted -> Bool wasReformatted source reformatted =- not (null (suggestions reformatted)) || source /= reformattedSource reformatted+ not (null (suggestions reformatted)) ||+ source /= reformattedSource reformatted
src/Language/Haskell/Source/Enumerator.hs view
@@ -1,4 +1,7 @@-module Language.Haskell.Source.Enumerator (enumeratePath, HaskellSourceFilePath) where+module Language.Haskell.Source.Enumerator+ ( enumeratePath+ , HaskellSourceFilePath+ ) where import Control.Applicative import Control.Monad@@ -63,7 +66,8 @@ else directory path getDirectoryContentsFullPaths :: FilePath -> IO [FilePath]-getDirectoryContentsFullPaths path = mkFull . notHidden . notMeta <$> getDirectoryContents path+getDirectoryContentsFullPaths path =+ mkFull . notHidden . notMeta <$> getDirectoryContents path where mkFull = map (path </>) notHidden = filter (not . isPrefixOf ".")@@ -84,8 +88,12 @@ sourcePaths :: GenericPackageDescription -> [FilePath] sourcePaths pkg = nub $ concatMap ($ pkg) pathExtractors where- pathExtractors = [ maybe [] (hsSourceDirs . libBuildInfo . condTreeData) . condLibrary- , concatMap (hsSourceDirs . buildInfo . condTreeData . snd) . condExecutables- , concatMap (hsSourceDirs . testBuildInfo . condTreeData . snd) . condTestSuites- , concatMap (hsSourceDirs . benchmarkBuildInfo . condTreeData . snd) . condBenchmarks- ]+ pathExtractors =+ [ maybe [] (hsSourceDirs . libBuildInfo . condTreeData) . condLibrary+ , concatMap (hsSourceDirs . buildInfo . condTreeData . snd) .+ condExecutables+ , concatMap (hsSourceDirs . testBuildInfo . condTreeData . snd) .+ condTestSuites+ , concatMap (hsSourceDirs . benchmarkBuildInfo . condTreeData . snd) .+ condBenchmarks+ ]
+ src/Path/Find.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE DataKinds #-}++-- | Finding files.+-- Lifted from Stack.+module Path.Find+ ( findFileUp+ ) where++import Control.Exception (evaluate)+import Control.Monad+import Control.Monad.Catch+import Control.Monad.IO.Class+import Data.List+import Path+import Path.IO hiding (findFiles)+import System.IO.Error (isPermissionError)++-- | Find the location of a file matching the given predicate.+findFileUp ::+ (MonadIO m, MonadThrow m)+ => Path Abs Dir -- ^ Start here.+ -> (Path Abs File -> Bool) -- ^ Predicate to match the file.+ -> Maybe (Path Abs Dir) -- ^ Do not ascend above this directory.+ -> m (Maybe (Path Abs File)) -- ^ Absolute file path.+findFileUp = findPathUp snd++-- | Find the location of a directory matching the given predicate.+findDirUp ::+ (MonadIO m, MonadThrow m)+ => Path Abs Dir -- ^ Start here.+ -> (Path Abs Dir -> Bool) -- ^ Predicate to match the directory.+ -> Maybe (Path Abs Dir) -- ^ Do not ascend above this directory.+ -> m (Maybe (Path Abs Dir)) -- ^ Absolute directory path.+findDirUp = findPathUp fst++-- | Find the location of a path matching the given predicate.+findPathUp ::+ (MonadIO m, MonadThrow m)+ => (([Path Abs Dir], [Path Abs File]) -> [Path Abs t])+ -- ^ Choose path type from pair.+ -> Path Abs Dir -- ^ Start here.+ -> (Path Abs t -> Bool) -- ^ Predicate to match the path.+ -> Maybe (Path Abs Dir) -- ^ Do not ascend above this directory.+ -> m (Maybe (Path Abs t)) -- ^ Absolute path.+findPathUp pathType dir p upperBound = do+ entries <- listDir dir+ case find p (pathType entries) of+ Just path -> return (Just path)+ Nothing+ | Just dir == upperBound -> return Nothing+ | parent dir == dir -> return Nothing+ | otherwise -> findPathUp pathType (parent dir) p upperBound
test/pure/Spec.hs view
@@ -1,4 +1,6 @@-module Main where+module Main+ ( main+ ) where import Test.Framework (defaultMain, testGroup) import Test.Framework.Providers.HUnit
test/self-formatting/Spec.hs view
@@ -1,4 +1,6 @@-module Main where+module Main+ ( main+ ) where import Language.Haskell.Format.Utilities @@ -7,7 +9,9 @@ import Test.HUnit hiding (Test) main :: IO ()-main = defaultMain- [ testGroup "Check formatting of package sources"- (hUnitTestToTests $ hunitTest "hfmt.cabal")- ]+main =+ defaultMain+ [ testGroup+ "Check formatting of package sources"+ (hUnitTestToTests $ hunitTest "hfmt.cabal")+ ]