hfmt 0.0.2.2 → 0.0.2.3
raw patch · 18 files changed
+727/−716 lines, 18 filesdep ~hindentdep ~stylish-haskellsetup-changedPVP ok
version bump matches the API change (PVP)
Dependency ranges changed: hindent, stylish-haskell
API changes (from Hackage documentation)
Files
- LICENSE +22/−22
- README.md +57/−46
- Setup.hs +2/−2
- app/Actions.hs +49/−49
- app/Main.hs +65/−65
- app/OptionsParser.hs +77/−77
- app/Types.hs +31/−31
- hfmt.cabal +78/−78
- src/Language/Haskell/Format.hs +41/−41
- src/Language/Haskell/Format/Definitions.hs +31/−31
- src/Language/Haskell/Format/HIndent.hs +28/−28
- src/Language/Haskell/Format/HLint.hs +40/−40
- src/Language/Haskell/Format/Internal.hs +11/−11
- src/Language/Haskell/Format/Stylish.hs +23/−23
- src/Language/Haskell/Format/Utilities.hs +60/−60
- src/Language/Haskell/Source/Enumerator.hs +91/−91
- test/pure/Spec.hs +8/−8
- test/self-formatting/Spec.hs +13/−13
LICENSE view
@@ -1,22 +1,22 @@-The MIT License (MIT) - -Copyright (c) 2014 Daniel Stiner - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. - +The MIT License (MIT)++Copyright (c) 2014 Daniel Stiner++Permission is hereby granted, free of charge, to any person obtaining a copy+of this software and associated documentation files (the "Software"), to deal+in the Software without restriction, including without limitation the rights+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell+copies of the Software, and to permit persons to whom the Software is+furnished to do so, subject to the following conditions:++The above copyright notice and this permission notice shall be included in+all copies or substantial portions of the Software.++THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN+THE SOFTWARE.+
README.md view
@@ -1,47 +1,58 @@-## hfmt [](https://travis-ci.org/danstiner/hfmt) - -hfmt is a tool for formatting Haskell programs. Currently it is simply a gofmt style wrapper of the excellent tools [hlint](https://github.com/ndmitchell/hlint/blob/master/README.md), [hindent](https://github.com/chrisdone/hindent#readme), and [stylish-haskell](https://github.com/jaspervdj/stylish-haskell#readme). - - -## Installation - - $ cabal install hfmt - -## Usage - -Check all Haskell source in the current directory: - - hfmt - -Overwrite any files with formatting changes: - - hfmt -w - -## Help text - - λ hfmt --help - hfmt - format Haskell programs - - Usage: hfmt.exe [-d|--print-diffs] [-s|--print-sources] [-l|--print-paths] - [-w|--write-sources] [PATH] - Operates on Haskell source files, reformatting them by applying suggestions - from HLint, hindent, and stylish-haskell. Inspired by the gofmt utility. - - Available options: - -h,--help Show this help text - -d,--print-diffs If a file's formatting is different, print a diff. - -s,--print-sources If a file's formatting is different, print its - source. - -l,--print-paths If a file's formatting is different, print its path. - -w,--write-sources If a file's formatting is different, overwrite it. - PATH Explicit paths to process. - - A single '-' will process standard input. - - Files will be processed directly. - - Directories will be recursively searched for - source files to process. - - .cabal files will be parsed and all specified - source directories and files processed. - - 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 +hfmt+====++[](https://hackage.haskell.org/package/hfmt)+[](https://github.com/danstiner/hfmt/blob/master/LICENSE)+[](https://travis-ci.org/danstiner/hfmt)++hfmt is a tool for formatting Haskell programs. Currently it is simply a gofmt style wrapper of the excellent tools [hlint](https://github.com/ndmitchell/hlint/blob/master/README.md), [hindent](https://github.com/chrisdone/hindent#readme), and [stylish-haskell](https://github.com/jaspervdj/stylish-haskell#readme).+++## Installation++with [stack](https://www.haskellstack.org/)++ $ cabal install hfmt++with [cabal](https://www.haskell.org/haskellwiki/Cabal/How_to_install_a_Cabal_package)++ $ stack install hfmt++## Usage++Check all Haskell source under the current directory:++ hfmt++Overwrite files with formatting suggestions:++ hfmt -w++## Help text++ λ hfmt --help+ hfmt - format Haskell programs++ Usage: hfmt.exe [-d|--print-diffs] [-s|--print-sources] [-l|--print-paths]+ [-w|--write-sources] [PATH]+ Operates on Haskell source files, reformatting them by applying suggestions+ from HLint, hindent, and stylish-haskell. Inspired by the gofmt utility.++ Available options:+ -h,--help Show this help text+ -d,--print-diffs If a file's formatting is different, print a diff.+ -s,--print-sources If a file's formatting is different, print its+ source.+ -l,--print-paths If a file's formatting is different, print its path.+ -w,--write-sources If a file's formatting is different, overwrite it.+ PATH Explicit paths to process.+ - A single '-' will process standard input.+ - Files will be processed directly.+ - Directories will be recursively searched for+ source files to process.+ - .cabal files will be parsed and all specified+ source directories and files processed.+ - 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.
Setup.hs view
@@ -1,2 +1,2 @@-import Distribution.Simple -main = defaultMain +import Distribution.Simple+main = defaultMain
app/Actions.hs view
@@ -1,49 +1,49 @@-module Actions (act) where - -import Language.Haskell.Format -import OptionsParser -import Types - -import Control.Monad -import Data.Algorithm.Diff -import Data.Algorithm.DiffContext -import Data.Algorithm.DiffOutput -import Text.PrettyPrint - -act :: Options -> ReformatResult -> IO ReformatResult -act options r@(InvalidReformat input errorString) = do - putStrLn ("Error reformatting " ++ show input ++ ": " ++ errorString) - return r -act options r@(Reformat input source result) = act' (optAction options) - where - act' PrintDiffs = when wasReformatted (printDiff input source result) >> return r - act' PrintSources = undefined - act' PrintFilePaths = when wasReformatted (print input) >> return r - act' WriteSources = do - when wasReformatted (writeSource input (reformattedSource result)) - return (Reformat input (reformattedSource result) result) - wasReformatted = sourceChangedOrHasSuggestions source result - -sourceChangedOrHasSuggestions :: HaskellSource -> Reformatted -> Bool -sourceChangedOrHasSuggestions source reformatted = - not (null (suggestions reformatted)) || source /= reformattedSource reformatted - -printDiff :: InputFile -> HaskellSource -> Reformatted -> IO () -printDiff (InputFilePath path) source reformatted = do - putStrLn (path ++ ":") - mapM_ (putStr . show) (suggestions reformatted) - putStr (showDiff source (reformattedSource reformatted)) -printDiff InputFromStdIn source reformatted = do - mapM_ (putStr . show) (suggestions reformatted) - putStr (showDiff source (reformattedSource reformatted)) - -showDiff :: HaskellSource -> HaskellSource -> String -showDiff (HaskellSource a) (HaskellSource b) = render (toDoc diff) - where - toDoc = prettyContextDiff (text "Original") (text "Reformatted") text - diff = getContextDiff linesOfContext (lines a) (lines b) - linesOfContext = 1 - -writeSource :: InputFile -> HaskellSource -> IO () -writeSource (InputFilePath path) (HaskellSource source) = writeFile path source -writeSource InputFromStdIn (HaskellSource source) = putStr source +module Actions (act) where++import Language.Haskell.Format+import OptionsParser+import Types++import Control.Monad+import Data.Algorithm.Diff+import Data.Algorithm.DiffContext+import Data.Algorithm.DiffOutput+import Text.PrettyPrint++act :: Options -> ReformatResult -> IO ReformatResult+act options r@(InvalidReformat input errorString) = do+ putStrLn ("Error reformatting " ++ show input ++ ": " ++ errorString)+ return r+act options r@(Reformat input source result) = act' (optAction options)+ where+ act' PrintDiffs = when wasReformatted (printDiff input source result) >> return r+ act' PrintSources = undefined+ act' PrintFilePaths = when wasReformatted (print input) >> return r+ act' WriteSources = do+ when wasReformatted (writeSource input (reformattedSource result))+ return (Reformat input (reformattedSource result) result)+ wasReformatted = sourceChangedOrHasSuggestions source result++sourceChangedOrHasSuggestions :: HaskellSource -> Reformatted -> Bool+sourceChangedOrHasSuggestions source reformatted =+ not (null (suggestions reformatted)) || source /= reformattedSource reformatted++printDiff :: InputFile -> HaskellSource -> Reformatted -> IO ()+printDiff (InputFilePath path) source reformatted = do+ putStrLn (path ++ ":")+ mapM_ (putStr . show) (suggestions reformatted)+ putStr (showDiff source (reformattedSource reformatted))+printDiff InputFromStdIn source reformatted = do+ mapM_ (putStr . show) (suggestions reformatted)+ putStr (showDiff source (reformattedSource reformatted))++showDiff :: HaskellSource -> HaskellSource -> String+showDiff (HaskellSource a) (HaskellSource b) = render (toDoc diff)+ where+ toDoc = prettyContextDiff (text "Original") (text "Reformatted") text+ diff = getContextDiff linesOfContext (lines a) (lines b)+ linesOfContext = 1++writeSource :: InputFile -> HaskellSource -> IO ()+writeSource (InputFilePath path) (HaskellSource source) = writeFile path source+writeSource InputFromStdIn (HaskellSource source) = putStr source
app/Main.hs view
@@ -1,65 +1,65 @@-module Main (main) where - -import Actions -import Language.Haskell.Format -import Language.Haskell.Format.Utilities hiding (wasReformatted) -import Language.Haskell.Source.Enumerator -import OptionsParser as Options -import Types - -import Control.Applicative -import Control.Monad -import Data.List -import Data.Maybe -import Data.Monoid -import Options.Applicative.Extra as OptApp -import Pipes -import qualified Pipes.Prelude as P -import System.Exit - -main :: IO () -main = do - options <- execParser Options.parser - formatter <- defaultFormatter - reformatNeeded <- runFormatter formatter options - if reformatNeeded - then exitFailure - else exitSuccess - -runFormatter :: Formatter -> Options -> IO Bool -runFormatter formatter options = - 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 - inputFiles = readInputFiles options - reformat = applyFormatter formatter - writeOutput = Actions.act options - -readInputFiles :: Options -> Producer InputFileWithSource IO () -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 - -readInputFile :: InputFile -> IO InputFileWithSource -readInputFile (InputFilePath path) = InputFileWithSource (InputFilePath path) <$> readSource path -readInputFile InputFromStdIn = InputFileWithSource InputFromStdIn <$> readStdin - -applyFormatter :: Formatter -> InputFileWithSource -> ReformatResult -applyFormatter (Formatter format) (InputFileWithSource input source) = - case format source of - Left error -> InvalidReformat input error - Right reformatted -> Reformat input source reformatted - -readSource :: HaskellSourceFilePath -> IO HaskellSource -readSource path = HaskellSource <$> readFile path - -readStdin :: IO HaskellSource -readStdin = HaskellSource <$> getContents - -sourceChangedOrHasSuggestions :: ReformatResult -> Bool -sourceChangedOrHasSuggestions (Reformat input source reformatted) = - not (null (suggestions reformatted)) || source /= reformattedSource reformatted +module Main (main) where++import Actions+import Language.Haskell.Format+import Language.Haskell.Format.Utilities hiding (wasReformatted)+import Language.Haskell.Source.Enumerator+import OptionsParser as Options+import Types++import Control.Applicative+import Control.Monad+import Data.List+import Data.Maybe+import Data.Monoid+import Options.Applicative.Extra as OptApp+import Pipes+import qualified Pipes.Prelude as P+import System.Exit++main :: IO ()+main = do+ options <- execParser Options.parser+ formatter <- defaultFormatter+ reformatNeeded <- runFormatter formatter options+ if reformatNeeded+ then exitFailure+ else exitSuccess++runFormatter :: Formatter -> Options -> IO Bool+runFormatter formatter options =+ 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+ inputFiles = readInputFiles options+ reformat = applyFormatter formatter+ writeOutput = Actions.act options++readInputFiles :: Options -> Producer InputFileWithSource IO ()+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++readInputFile :: InputFile -> IO InputFileWithSource+readInputFile (InputFilePath path) = InputFileWithSource (InputFilePath path) <$> readSource path+readInputFile InputFromStdIn = InputFileWithSource InputFromStdIn <$> readStdin++applyFormatter :: Formatter -> InputFileWithSource -> ReformatResult+applyFormatter (Formatter format) (InputFileWithSource input source) =+ case format source of+ Left error -> InvalidReformat input error+ Right reformatted -> Reformat input source reformatted++readSource :: HaskellSourceFilePath -> IO HaskellSource+readSource path = HaskellSource <$> readFile path++readStdin :: IO HaskellSource+readStdin = HaskellSource <$> getContents++sourceChangedOrHasSuggestions :: ReformatResult -> Bool+sourceChangedOrHasSuggestions (Reformat input source reformatted) =+ not (null (suggestions reformatted)) || source /= reformattedSource reformatted
app/OptionsParser.hs view
@@ -1,77 +1,77 @@-module OptionsParser (Options, optAction, optPaths, parser) where - -import Types - -import Control.Applicative -import Data.List -import Data.Monoid -import Options.Applicative.Builder -import Options.Applicative.Common -import Options.Applicative.Extra -import Text.PrettyPrint.ANSI.Leijen hiding (empty, (<$>), (<>)) - -data Options = - Options - { optPrintDiffs :: Bool - , optPrintSources :: Bool - , optPrintFilePaths :: Bool - , optWriteSources :: Bool - , optPaths :: [FilePath] - } - -optAction :: Options -> Action -optAction options - | optPrintDiffs options = PrintDiffs - | optPrintFilePaths options = PrintFilePaths - | optPrintSources options = PrintSources - | optWriteSources options = WriteSources - | optPaths options == ["-"] = PrintSources - | 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 - 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." - ] - -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) - -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.") - -parser :: ParserInfo Options -parser = optionParserInfo +module OptionsParser (Options, optAction, optPaths, parser) where++import Types++import Control.Applicative+import Data.List+import Data.Monoid+import Options.Applicative.Builder+import Options.Applicative.Common+import Options.Applicative.Extra+import Text.PrettyPrint.ANSI.Leijen hiding (empty, (<$>), (<>))++data Options =+ Options+ { optPrintDiffs :: Bool+ , optPrintSources :: Bool+ , optPrintFilePaths :: Bool+ , optWriteSources :: Bool+ , optPaths :: [FilePath]+ }++optAction :: Options -> Action+optAction options+ | optPrintDiffs options = PrintDiffs+ | optPrintFilePaths options = PrintFilePaths+ | optPrintSources options = PrintSources+ | optWriteSources options = WriteSources+ | optPaths options == ["-"] = PrintSources+ | 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+ 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."+ ]++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)++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.")++parser :: ParserInfo Options+parser = optionParserInfo
app/Types.hs view
@@ -1,31 +1,31 @@-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 InputFile = InputFilePath HaskellSourceFilePath - | InputFromStdIn - -instance Show InputFile where - show (InputFilePath path) = path - show InputFromStdIn = "-" - -data InputFileWithSource = InputFileWithSource InputFile HaskellSource - -type ErrorString = String - -data ReformatResult = InvalidReformat InputFile ErrorString - | Reformat InputFile HaskellSource Reformatted +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 InputFile = InputFilePath HaskellSourceFilePath+ | InputFromStdIn++instance Show InputFile where+ show (InputFilePath path) = path+ show InputFromStdIn = "-"++data InputFileWithSource = InputFileWithSource InputFile HaskellSource++type ErrorString = String++data ReformatResult = InvalidReformat InputFile ErrorString+ | Reformat InputFile HaskellSource Reformatted
hfmt.cabal view
@@ -1,78 +1,78 @@-name: hfmt -version: 0.0.2.2 -synopsis: Haskell source code formatter -description: Inspired by gofmt. Built using hlint, hindent, and stylish-haskell. -license: MIT -license-file: LICENSE -author: Daniel Stiner -maintainer: Daniel Stiner <daniel.stiner@gmail.com> -stability: Experimental -homepage: http://github.com/danstiner/hfmt -bug-reports: http://github.com/danstiner/hfmt/issues -category: Language -build-type: Simple -extra-source-files: README.md -cabal-version: >=1.9.2 -tested-with: GHC >= 7.10 - -library - Hs-Source-Dirs: src - Exposed-Modules: Language.Haskell.Format - , Language.Haskell.Format.Utilities - , Language.Haskell.Source.Enumerator - Other-Modules: Language.Haskell.Format.Internal - , Language.Haskell.Format.Definitions - , Language.Haskell.Format.HIndent - , Language.Haskell.Format.HLint - , Language.Haskell.Format.Stylish - GHC-Options: -Wall - Build-Depends: base >= 4.8 && < 5 - , Cabal - , directory - , filepath - , haskell-src-exts - , hindent >= 4.5 - , hlint >= 1.9.13 , hlint < 2 - , HUnit - , pipes - , stylish-haskell - , text - -executable hfmt - Hs-Source-Dirs: app - Main-Is: Main.hs - Other-Modules: Actions - , OptionsParser - , Types - GHC-Options: -Wall - Build-Depends: base == 4.* - , hfmt - , ansi-wl-pprint - , Diff - , optparse-applicative - , pipes - , pretty - -test-suite self-formatting-test - Type: exitcode-stdio-1.0 - Hs-Source-Dirs: test/self-formatting - Main-Is: Spec.hs - Build-Depends: base == 4.* - , hfmt - , HUnit - , test-framework - , test-framework-hunit - -test-suite pure-test - Type: exitcode-stdio-1.0 - Hs-Source-Dirs: test/pure - Main-Is: Spec.hs - Build-Depends: base == 4.* - , hfmt - , HUnit - , test-framework - , test-framework-hunit - -source-repository head - type: git - location: git://github.com:danstiner/hfmt.git +name: hfmt+version: 0.0.2.3+synopsis: Haskell source code formatter+description: Inspired by gofmt. Built using hlint, hindent, and stylish-haskell.+license: MIT+license-file: LICENSE+author: Daniel Stiner+maintainer: Daniel Stiner <daniel.stiner@gmail.com>+stability: Experimental+homepage: http://github.com/danstiner/hfmt+bug-reports: http://github.com/danstiner/hfmt/issues+category: Language+build-type: Simple+extra-source-files: README.md+cabal-version: >=1.9.2+tested-with: GHC >= 7.10++library+ Hs-Source-Dirs: src+ Exposed-Modules: Language.Haskell.Format+ , Language.Haskell.Format.Utilities+ , Language.Haskell.Source.Enumerator+ Other-Modules: Language.Haskell.Format.Internal+ , Language.Haskell.Format.Definitions+ , Language.Haskell.Format.HIndent+ , Language.Haskell.Format.HLint+ , Language.Haskell.Format.Stylish+ GHC-Options: -Wall+ Build-Depends: base >= 4.8 && < 5+ , Cabal+ , directory+ , filepath+ , haskell-src-exts+ , hindent >= 4.5 , hindent < 5+ , hlint >= 1.9.13 , hlint < 2+ , HUnit+ , pipes+ , stylish-haskell >= 0.5 , stylish-haskell < 0.6+ , text++executable hfmt+ Hs-Source-Dirs: app+ Main-Is: Main.hs+ Other-Modules: Actions+ , OptionsParser+ , Types+ GHC-Options: -Wall+ Build-Depends: base == 4.*+ , hfmt+ , ansi-wl-pprint+ , Diff+ , optparse-applicative+ , pipes+ , pretty++test-suite self-formatting-test+ Type: exitcode-stdio-1.0+ Hs-Source-Dirs: test/self-formatting+ Main-Is: Spec.hs+ Build-Depends: base == 4.*+ , hfmt+ , HUnit+ , test-framework+ , test-framework-hunit++test-suite pure-test+ Type: exitcode-stdio-1.0+ Hs-Source-Dirs: test/pure+ Main-Is: Spec.hs+ Build-Depends: base == 4.*+ , hfmt+ , HUnit+ , test-framework+ , test-framework-hunit++source-repository head+ type: git+ location: git://github.com:danstiner/hfmt.git
src/Language/Haskell/Format.hs view
@@ -1,41 +1,41 @@-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 -import qualified Language.Haskell.Format.HLint as HLint -import qualified Language.Haskell.Format.Stylish as Stylish - -import Control.Applicative -import Data.Maybe - -data Settings = Settings - -autoSettings :: IO Settings -autoSettings = return Settings - -hlint :: Settings -> IO Formatter -hlint _ = HLint.suggester <$> HLint.autoSettings - -hindent :: Settings -> IO Formatter -hindent _ = HIndent.formatter <$> HIndent.autoSettings - -stylish :: Settings -> IO Formatter -stylish _ = Stylish.formatter <$> Stylish.autoSettings - -formatters :: Settings -> IO [Formatter] -formatters s = sequence [hlint s, hindent s, stylish s] - -format :: Formatter -> HaskellSource -> Either String Reformatted -format = unFormatter +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+import qualified Language.Haskell.Format.HLint as HLint+import qualified Language.Haskell.Format.Stylish as Stylish++import Control.Applicative+import Data.Maybe++data Settings = Settings++autoSettings :: IO Settings+autoSettings = return Settings++hlint :: Settings -> IO Formatter+hlint _ = HLint.suggester <$> HLint.autoSettings++hindent :: Settings -> IO Formatter+hindent _ = HIndent.formatter <$> HIndent.autoSettings++stylish :: Settings -> IO Formatter+stylish _ = Stylish.formatter <$> Stylish.autoSettings++formatters :: Settings -> IO [Formatter]+formatters s = sequence [hlint s, hindent s, stylish s]++format :: Formatter -> HaskellSource -> Either String Reformatted+format = unFormatter
src/Language/Haskell/Format/Definitions.hs view
@@ -1,31 +1,31 @@-module Language.Haskell.Format.Definitions (HaskellSource(..), Reformatted(..), Formatter(..), Suggestion(..)) where - -import Control.Applicative -import Control.Monad -import Data.Monoid - -type ErrorString = String - -newtype HaskellSource = HaskellSource String - deriving Eq - -newtype Suggestion = Suggestion String - -instance Show Suggestion where - show (Suggestion text) = text - -data Reformatted = Reformatted { reformattedSource :: HaskellSource, suggestions :: [Suggestion] } - -instance Monoid Reformatted where - mempty = Reformatted undefined [] - (Reformatted _ suggestionsA) `mappend` (Reformatted sourceB suggestionsB) = Reformatted sourceB - (suggestionsA <> suggestionsB) - -data 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 formatter r = (r <>) <$> formatter (reformattedSource r) +module Language.Haskell.Format.Definitions (HaskellSource(..), Reformatted(..), Formatter(..), Suggestion(..)) where++import Control.Applicative+import Control.Monad+import Data.Monoid++type ErrorString = String++newtype HaskellSource = HaskellSource String+ deriving Eq++newtype Suggestion = Suggestion String++instance Show Suggestion where+ show (Suggestion text) = text++data Reformatted = Reformatted { reformattedSource :: HaskellSource, suggestions :: [Suggestion] }++instance Monoid Reformatted where+ mempty = Reformatted undefined []+ (Reformatted _ suggestionsA) `mappend` (Reformatted sourceB suggestionsB) = Reformatted sourceB+ (suggestionsA <> suggestionsB)++data 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 formatter r = (r <>) <$> formatter (reformattedSource r)
src/Language/Haskell/Format/HIndent.hs view
@@ -1,28 +1,28 @@-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 Language.Haskell.Format.Definitions -import Language.Haskell.Format.Internal - -data Settings = Settings Style (Maybe [Extension]) - -defaultFormatter :: IO Formatter -defaultFormatter = formatter <$> autoSettings - -autoSettings :: IO Settings -autoSettings = return (Settings gibiansky Nothing) - -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 - where - sourceText = L.pack source +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 Language.Haskell.Format.Definitions+import Language.Haskell.Format.Internal++data Settings = Settings Style (Maybe [Extension])++defaultFormatter :: IO Formatter+defaultFormatter = formatter <$> autoSettings++autoSettings :: IO Settings+autoSettings = return (Settings gibiansky Nothing)++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+ where+ sourceText = L.pack source
src/Language/Haskell/Format/HLint.hs view
@@ -1,40 +1,40 @@-module Language.Haskell.Format.HLint (autoSettings, formatter, suggester) where - -import Language.Haskell.Format.Definitions -import Language.Haskell.Format.Internal - -import Control.Applicative -import Language.Haskell.Exts.Annotated as Hse -import qualified Language.Haskell.HLint3 as HLint3 - -formatter = undefined - -suggester :: (ParseMode, [HLint3.Classify], HLint3.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) - 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) - -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) ++ ")" - -ideaToSuggestion :: HLint3.Idea -> Suggestion -ideaToSuggestion = Suggestion . show +module Language.Haskell.Format.HLint (autoSettings, formatter, suggester) where++import Language.Haskell.Format.Definitions+import Language.Haskell.Format.Internal++import Control.Applicative+import Language.Haskell.Exts.Annotated as Hse+import qualified Language.Haskell.HLint3 as HLint3++formatter = undefined++suggester :: (ParseMode, [HLint3.Classify], HLint3.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)+ 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)++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) ++ ")"++ideaToSuggestion :: HLint3.Idea -> Suggestion+ideaToSuggestion = Suggestion . show
src/Language/Haskell/Format/Internal.hs view
@@ -1,11 +1,11 @@-module Language.Haskell.Format.Internal (mkFormatter, mkSuggester) where - -import Language.Haskell.Format.Definitions - -import Control.Applicative - -mkFormatter :: (HaskellSource -> Either String HaskellSource) -> Formatter -mkFormatter f = Formatter (fmap (\source -> Reformatted source []) . f) - -mkSuggester :: (HaskellSource -> Either String [Suggestion]) -> Formatter -mkSuggester f = Formatter $ \source -> Reformatted source <$> f source +module Language.Haskell.Format.Internal (mkFormatter, mkSuggester) where++import Language.Haskell.Format.Definitions++import Control.Applicative++mkFormatter :: (HaskellSource -> Either String HaskellSource) -> Formatter+mkFormatter f = Formatter (fmap (\source -> Reformatted source []) . f)++mkSuggester :: (HaskellSource -> Either String [Suggestion]) -> Formatter+mkSuggester f = Formatter $ \source -> Reformatted source <$> f source
src/Language/Haskell/Format/Stylish.hs view
@@ -1,23 +1,23 @@-module Language.Haskell.Format.Stylish (autoSettings, formatter) where - -import Control.Applicative -import Language.Haskell.Stylish as Stylish - -import Language.Haskell.Format.Definitions -import Language.Haskell.Format.Internal - -data Settings = Settings Stylish.Config - -autoSettings :: IO Settings -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 - where - sourceLines = lines source - extensions = Stylish.configLanguageExtensions config - steps = Stylish.configSteps config +module Language.Haskell.Format.Stylish (autoSettings, formatter) where++import Control.Applicative+import Language.Haskell.Stylish as Stylish++import Language.Haskell.Format.Definitions+import Language.Haskell.Format.Internal++data Settings = Settings Stylish.Config++autoSettings :: IO Settings+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+ where+ sourceLines = lines source+ extensions = Stylish.configLanguageExtensions config+ steps = Stylish.configSteps config
src/Language/Haskell/Format/Utilities.hs view
@@ -1,60 +1,60 @@-module Language.Haskell.Format.Utilities (wasReformatted, hunitTest, defaultFormatter) where - -import Language.Haskell.Format -import Language.Haskell.Format.Definitions -import Language.Haskell.Source.Enumerator - -import Control.Applicative -import Control.Monad -import Data.Monoid -import Pipes -import qualified Pipes.Prelude as P -import Test.HUnit - -type ErrorString = String - -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 - -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)) - -check :: Formatter -> FilePath -> Producer CheckResult IO () -check formatter path = enumeratePath path >-> - P.mapM readSource >-> - P.map (checkFormatting formatter) - -readSource :: HaskellSourceFilePath -> IO HaskellSource -readSource path = HaskellSource <$> readFile path - -checkFormatting :: Formatter -> HaskellSource -> CheckResult -checkFormatting (Formatter format) source = - case format source of - Left error -> InvalidCheckResult error - Right reformatted -> CheckResult source reformatted - -fix :: Formatter -> FilePath -> IO () -fix = undefined - -defaultFormatter :: IO Formatter -defaultFormatter = mconcat <$> (autoSettings >>= formatters) - -wasReformatted :: HaskellSource -> Reformatted -> Bool -wasReformatted source reformatted = - not (null (suggestions reformatted)) || source /= reformattedSource reformatted +module Language.Haskell.Format.Utilities (wasReformatted, hunitTest, defaultFormatter) where++import Language.Haskell.Format+import Language.Haskell.Format.Definitions+import Language.Haskell.Source.Enumerator++import Control.Applicative+import Control.Monad+import Data.Monoid+import Pipes+import qualified Pipes.Prelude as P+import Test.HUnit++type ErrorString = String++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++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))++check :: Formatter -> FilePath -> Producer CheckResult IO ()+check formatter path = enumeratePath path >->+ P.mapM readSource >->+ P.map (checkFormatting formatter)++readSource :: HaskellSourceFilePath -> IO HaskellSource+readSource path = HaskellSource <$> readFile path++checkFormatting :: Formatter -> HaskellSource -> CheckResult+checkFormatting (Formatter format) source =+ case format source of+ Left error -> InvalidCheckResult error+ Right reformatted -> CheckResult source reformatted++fix :: Formatter -> FilePath -> IO ()+fix = undefined++defaultFormatter :: IO Formatter+defaultFormatter = mconcat <$> (autoSettings >>= formatters)++wasReformatted :: HaskellSource -> Reformatted -> Bool+wasReformatted source reformatted =+ not (null (suggestions reformatted)) || source /= reformattedSource reformatted
src/Language/Haskell/Source/Enumerator.hs view
@@ -1,91 +1,91 @@-module Language.Haskell.Source.Enumerator (enumeratePath, HaskellSourceFilePath) where - -import Control.Applicative -import Control.Monad -import Data.List -import Distribution.PackageDescription -import Distribution.PackageDescription.Parse -import qualified Distribution.Verbosity as Verbosity -import Pipes -import System.Directory -import System.FilePath - -type HaskellSourceFilePath = FilePath - -enumeratePath :: FilePath -> Producer HaskellSourceFilePath IO () -enumeratePath = filePath - -filePath :: FilePath -> Producer HaskellSourceFilePath IO () -filePath path = do - isCabal <- lift $ isCabalFile path - if isCabal - then package' path - else directoryOrFile path - -simpleFilePath :: FilePath -> Producer HaskellSourceFilePath IO () -simpleFilePath path = do - isHaskellSource <- lift $ isHaskellSourceFile path - when isHaskellSource $ yield path - -simpleDirectory :: FilePath -> Producer HaskellSourceFilePath IO () -simpleDirectory path = do - contents <- lift $ getDirectoryContentsFullPaths path - mapM_ simpleFileOrDirectory contents - -simpleFileOrDirectory :: FilePath -> Producer HaskellSourceFilePath IO () -simpleFileOrDirectory filepath = do - dir <- lift $ doesDirectoryExist filepath - if dir - then simpleDirectory filepath - else simpleFilePath filepath - -package' :: FilePath -> Producer HaskellSourceFilePath IO () -package' path = readPackage path >>= expandPaths - where - readPackage = lift . readPackageDescription Verbosity.silent - expandPaths = mapM_ (simpleFileOrDirectory . mkFull) . sourcePaths - dir = dropFileName path - mkFull = (dir </>) - -directory :: FilePath -> Producer HaskellSourceFilePath IO () -directory path = do - contents <- lift $ getDirectoryContentsFullPaths path - cabalFiles <- lift $ filterM isCabalFile contents - if null cabalFiles - then mapM_ directoryOrFile contents - else mapM_ package' cabalFiles - -directoryOrFile :: FilePath -> Producer HaskellSourceFilePath IO () -directoryOrFile path = do - isFile <- lift $ doesFileExist path - if isFile - then simpleFilePath path - else directory path - -getDirectoryContentsFullPaths :: FilePath -> IO [FilePath] -getDirectoryContentsFullPaths path = mkFull . notHidden . notMeta <$> getDirectoryContents path - where - mkFull = map (path </>) - notHidden = filter (not . isPrefixOf ".") - notMeta = (\\ [".", ".."]) - -isCabalFile :: FilePath -> IO Bool -isCabalFile path = (hasCabalExtension &&) <$> isFile - where - isFile = doesFileExist path - hasCabalExtension = ".cabal" `isSuffixOf` path - -isHaskellSourceFile :: FilePath -> IO Bool -isHaskellSourceFile path = (hasHaskellExtension &&) <$> isFile - where - isFile = doesFileExist path - hasHaskellExtension = ".hs" `isSuffixOf` path || ".lhs" `isSuffixOf` path - -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 - ] +module Language.Haskell.Source.Enumerator (enumeratePath, HaskellSourceFilePath) where++import Control.Applicative+import Control.Monad+import Data.List+import Distribution.PackageDescription+import Distribution.PackageDescription.Parse+import qualified Distribution.Verbosity as Verbosity+import Pipes+import System.Directory+import System.FilePath++type HaskellSourceFilePath = FilePath++enumeratePath :: FilePath -> Producer HaskellSourceFilePath IO ()+enumeratePath = filePath++filePath :: FilePath -> Producer HaskellSourceFilePath IO ()+filePath path = do+ isCabal <- lift $ isCabalFile path+ if isCabal+ then package' path+ else directoryOrFile path++simpleFilePath :: FilePath -> Producer HaskellSourceFilePath IO ()+simpleFilePath path = do+ isHaskellSource <- lift $ isHaskellSourceFile path+ when isHaskellSource $ yield path++simpleDirectory :: FilePath -> Producer HaskellSourceFilePath IO ()+simpleDirectory path = do+ contents <- lift $ getDirectoryContentsFullPaths path+ mapM_ simpleFileOrDirectory contents++simpleFileOrDirectory :: FilePath -> Producer HaskellSourceFilePath IO ()+simpleFileOrDirectory filepath = do+ dir <- lift $ doesDirectoryExist filepath+ if dir+ then simpleDirectory filepath+ else simpleFilePath filepath++package' :: FilePath -> Producer HaskellSourceFilePath IO ()+package' path = readPackage path >>= expandPaths+ where+ readPackage = lift . readPackageDescription Verbosity.silent+ expandPaths = mapM_ (simpleFileOrDirectory . mkFull) . sourcePaths+ dir = dropFileName path+ mkFull = (dir </>)++directory :: FilePath -> Producer HaskellSourceFilePath IO ()+directory path = do+ contents <- lift $ getDirectoryContentsFullPaths path+ cabalFiles <- lift $ filterM isCabalFile contents+ if null cabalFiles+ then mapM_ directoryOrFile contents+ else mapM_ package' cabalFiles++directoryOrFile :: FilePath -> Producer HaskellSourceFilePath IO ()+directoryOrFile path = do+ isFile <- lift $ doesFileExist path+ if isFile+ then simpleFilePath path+ else directory path++getDirectoryContentsFullPaths :: FilePath -> IO [FilePath]+getDirectoryContentsFullPaths path = mkFull . notHidden . notMeta <$> getDirectoryContents path+ where+ mkFull = map (path </>)+ notHidden = filter (not . isPrefixOf ".")+ notMeta = (\\ [".", ".."])++isCabalFile :: FilePath -> IO Bool+isCabalFile path = (hasCabalExtension &&) <$> isFile+ where+ isFile = doesFileExist path+ hasCabalExtension = ".cabal" `isSuffixOf` path++isHaskellSourceFile :: FilePath -> IO Bool+isHaskellSourceFile path = (hasHaskellExtension &&) <$> isFile+ where+ isFile = doesFileExist path+ hasHaskellExtension = ".hs" `isSuffixOf` path || ".lhs" `isSuffixOf` path++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+ ]
test/pure/Spec.hs view
@@ -1,8 +1,8 @@-module Main where - -import Test.Framework (defaultMain, testGroup) -import Test.Framework.Providers.HUnit -import Test.HUnit hiding (Test) - -main :: IO () -main = defaultMain [] +module Main where++import Test.Framework (defaultMain, testGroup)+import Test.Framework.Providers.HUnit+import Test.HUnit hiding (Test)++main :: IO ()+main = defaultMain []
test/self-formatting/Spec.hs view
@@ -1,13 +1,13 @@-module Main where - -import Language.Haskell.Format.Utilities - -import Test.Framework (defaultMain, testGroup) -import Test.Framework.Providers.HUnit -import Test.HUnit hiding (Test) - -main :: IO () -main = defaultMain - [ testGroup "Check formatting of package sources" - (hUnitTestToTests $ hunitTest "hfmt.cabal") - ] +module Main where++import Language.Haskell.Format.Utilities++import Test.Framework (defaultMain, testGroup)+import Test.Framework.Providers.HUnit+import Test.HUnit hiding (Test)++main :: IO ()+main = defaultMain+ [ testGroup "Check formatting of package sources"+ (hUnitTestToTests $ hunitTest "hfmt.cabal")+ ]