cabal-gild 1.0.2.4 → 1.1.0.0
raw patch · 14 files changed
+266/−100 lines, 14 filesPVP ok
version bump matches the API change (PVP)
API changes (from Hackage documentation)
- CabalGild.Class.MonadLog: log :: MonadLog m => String -> m ()
+ CabalGild.Exception.SpecifiedOutputWithCheckMode: SpecifiedOutputWithCheckMode :: SpecifiedOutputWithCheckMode
+ CabalGild.Exception.SpecifiedOutputWithCheckMode: data SpecifiedOutputWithCheckMode
+ CabalGild.Exception.SpecifiedOutputWithCheckMode: instance GHC.Classes.Eq CabalGild.Exception.SpecifiedOutputWithCheckMode.SpecifiedOutputWithCheckMode
+ CabalGild.Exception.SpecifiedOutputWithCheckMode: instance GHC.Exception.Type.Exception CabalGild.Exception.SpecifiedOutputWithCheckMode.SpecifiedOutputWithCheckMode
+ CabalGild.Exception.SpecifiedOutputWithCheckMode: instance GHC.Show.Show CabalGild.Exception.SpecifiedOutputWithCheckMode.SpecifiedOutputWithCheckMode
+ CabalGild.Exception.SpecifiedStdinWithFileInput: SpecifiedStdinWithFileInput :: SpecifiedStdinWithFileInput
+ CabalGild.Exception.SpecifiedStdinWithFileInput: data SpecifiedStdinWithFileInput
+ CabalGild.Exception.SpecifiedStdinWithFileInput: instance GHC.Classes.Eq CabalGild.Exception.SpecifiedStdinWithFileInput.SpecifiedStdinWithFileInput
+ CabalGild.Exception.SpecifiedStdinWithFileInput: instance GHC.Exception.Type.Exception CabalGild.Exception.SpecifiedStdinWithFileInput.SpecifiedStdinWithFileInput
+ CabalGild.Exception.SpecifiedStdinWithFileInput: instance GHC.Show.Show CabalGild.Exception.SpecifiedStdinWithFileInput.SpecifiedStdinWithFileInput
+ CabalGild.Type.Context: Context :: Input -> Mode -> Output -> FilePath -> Context
+ CabalGild.Type.Context: [input] :: Context -> Input
+ CabalGild.Type.Context: [mode] :: Context -> Mode
+ CabalGild.Type.Context: [output] :: Context -> Output
+ CabalGild.Type.Context: [stdin] :: Context -> FilePath
+ CabalGild.Type.Context: data Context
+ CabalGild.Type.Context: fromConfig :: (MonadLog m, MonadThrow m) => Config -> m Context
+ CabalGild.Type.Context: instance GHC.Classes.Eq CabalGild.Type.Context.Context
+ CabalGild.Type.Context: instance GHC.Show.Show CabalGild.Type.Context.Context
+ CabalGild.Type.Input: File :: FilePath -> Input
+ CabalGild.Type.Input: Stdin :: Input
+ CabalGild.Type.Input: data Input
+ CabalGild.Type.Input: fromString :: String -> Input
+ CabalGild.Type.Input: instance GHC.Classes.Eq CabalGild.Type.Input.Input
+ CabalGild.Type.Input: instance GHC.Classes.Ord CabalGild.Type.Input.Input
+ CabalGild.Type.Input: instance GHC.Show.Show CabalGild.Type.Input.Input
+ CabalGild.Type.Optional: Default :: Optional a
+ CabalGild.Type.Optional: Specific :: a -> Optional a
+ CabalGild.Type.Optional: data Optional a
+ CabalGild.Type.Optional: instance GHC.Classes.Eq a => GHC.Classes.Eq (CabalGild.Type.Optional.Optional a)
+ CabalGild.Type.Optional: instance GHC.Show.Show a => GHC.Show.Show (CabalGild.Type.Optional.Optional a)
+ CabalGild.Type.Optional: optional :: b -> (a -> b) -> Optional a -> b
+ CabalGild.Type.Optional: withDefault :: a -> Optional a -> a
+ CabalGild.Type.Output: File :: FilePath -> Output
+ CabalGild.Type.Output: Stdout :: Output
+ CabalGild.Type.Output: data Output
+ CabalGild.Type.Output: fromString :: String -> Output
+ CabalGild.Type.Output: instance GHC.Classes.Eq CabalGild.Type.Output.Output
+ CabalGild.Type.Output: instance GHC.Classes.Ord CabalGild.Type.Output.Output
+ CabalGild.Type.Output: instance GHC.Show.Show CabalGild.Type.Output.Output
- CabalGild.Class.MonadRead: read :: MonadRead m => Maybe FilePath -> m ByteString
+ CabalGild.Class.MonadRead: read :: MonadRead m => Input -> m ByteString
- CabalGild.Class.MonadWrite: write :: MonadWrite m => Maybe FilePath -> ByteString -> m ()
+ CabalGild.Class.MonadWrite: write :: MonadWrite m => Output -> ByteString -> m ()
- CabalGild.Main: mainWith :: (MonadLog m, MonadRead m, MonadThrow m, MonadWalk m, MonadWrite m) => String -> [String] -> m ()
+ CabalGild.Main: mainWith :: (MonadLog m, MonadRead m, MonadThrow m, MonadWalk m, MonadWrite m) => [String] -> m ()
- CabalGild.Type.Config: Config :: Bool -> Maybe FilePath -> Mode -> Maybe FilePath -> FilePath -> Bool -> Config
+ CabalGild.Type.Config: Config :: Optional Bool -> Optional Input -> Optional Mode -> Optional Output -> Optional FilePath -> Optional Bool -> Config
- CabalGild.Type.Config: [help] :: Config -> Bool
+ CabalGild.Type.Config: [help] :: Config -> Optional Bool
- CabalGild.Type.Config: [input] :: Config -> Maybe FilePath
+ CabalGild.Type.Config: [input] :: Config -> Optional Input
- CabalGild.Type.Config: [mode] :: Config -> Mode
+ CabalGild.Type.Config: [mode] :: Config -> Optional Mode
- CabalGild.Type.Config: [output] :: Config -> Maybe FilePath
+ CabalGild.Type.Config: [output] :: Config -> Optional Output
- CabalGild.Type.Config: [stdin] :: Config -> FilePath
+ CabalGild.Type.Config: [stdin] :: Config -> Optional FilePath
- CabalGild.Type.Config: [version] :: Config -> Bool
+ CabalGild.Type.Config: [version] :: Config -> Optional Bool
Files
- README.md +4/−4
- cabal-gild.cabal +7/−1
- source/library/CabalGild/Class/MonadLog.hs +4/−8
- source/library/CabalGild/Class/MonadRead.hs +6/−4
- source/library/CabalGild/Class/MonadWrite.hs +6/−4
- source/library/CabalGild/Exception/SpecifiedOutputWithCheckMode.hs +12/−0
- source/library/CabalGild/Exception/SpecifiedStdinWithFileInput.hs +13/−0
- source/library/CabalGild/Main.hs +15/−27
- source/library/CabalGild/Type/Config.hs +21/−22
- source/library/CabalGild/Type/Context.hs +73/−0
- source/library/CabalGild/Type/Input.hs +15/−0
- source/library/CabalGild/Type/Optional.hs +20/−0
- source/library/CabalGild/Type/Output.hs +15/−0
- source/test-suite/Main.hs +55/−30
README.md view
@@ -147,7 +147,7 @@ $ cabal-gild --input p.cabal --output p.cabal ``` - This option is ignored when the mode is `check`.+ It is an error to provide a value for this option when the mode is `check`. - `--stdin=FILE`: When reading input from STDIN, use `FILE` as the effective input file. This is useful when a file's contents are already available, like@@ -157,7 +157,7 @@ $ cabal-gild --stdin p.cabal < p.cabal ``` - This option is ignored when the input is not `-`.+ It is an error to provide a value for this option unless the input is `-`. ### Pragmas @@ -188,8 +188,8 @@ `signatures` fields. It will be ignored on all other fields. Any existing modules or signatures in the list will be ignored. The entire- field (including comments) will be replaced. This means adding, removing, and- renaming modules or signatures should be handled automatically.+ field will be replaced. This means adding, removing, and renaming modules or+ signatures should be handled automatically. This pragma searches for files with any of the following extensions: `*.chs`, `*.cpphs`, `*.gc`, `*.hs`, `*.hsc`, `*.hsig`, `*.lhs`, `*.lhsig`, `*.ly`,
cabal-gild.cabal view
@@ -11,7 +11,7 @@ maintainer: Taylor Fausak name: cabal-gild synopsis: Formats package descriptions.-version: 1.0.2.4+version: 1.1.0.0 source-repository head type: git@@ -85,6 +85,8 @@ CabalGild.Exception.InvalidMode CabalGild.Exception.InvalidOption CabalGild.Exception.ParseError+ CabalGild.Exception.SpecifiedOutputWithCheckMode+ CabalGild.Exception.SpecifiedStdinWithFileInput CabalGild.Exception.UnexpectedArgument CabalGild.Exception.UnknownOption CabalGild.Extra.Either@@ -100,17 +102,21 @@ CabalGild.Type.Chunk CabalGild.Type.Comment CabalGild.Type.Config+ CabalGild.Type.Context CabalGild.Type.Dependency CabalGild.Type.ExeDependency CabalGild.Type.Extension CabalGild.Type.Flag CabalGild.Type.ForeignLibOption+ CabalGild.Type.Input CabalGild.Type.Language CabalGild.Type.LegacyExeDependency CabalGild.Type.Line CabalGild.Type.List CabalGild.Type.Mode CabalGild.Type.ModuleReexport+ CabalGild.Type.Optional+ CabalGild.Type.Output CabalGild.Type.PkgconfigDependency CabalGild.Type.PkgconfigVersionRange CabalGild.Type.Pragma
source/library/CabalGild/Class/MonadLog.hs view
@@ -2,13 +2,9 @@ -- | A 'Monad' that can also log messages. class (Monad m) => MonadLog m where- -- | Logs the given message. Typical usage should prefer 'logLn'.- log :: String -> m ()+ -- | Logs the given message followed by a newline.+ logLn :: String -> m () --- | Uses 'putStr'.+-- | Uses 'putStrLn'. instance MonadLog IO where- log = putStr---- | Logs the message followed by a newline.-logLn :: (MonadLog m) => String -> m ()-logLn = CabalGild.Class.MonadLog.log . (<> "\n")+ logLn = putStrLn
source/library/CabalGild/Class/MonadRead.hs view
@@ -1,14 +1,16 @@ module CabalGild.Class.MonadRead where +import qualified CabalGild.Type.Input as Input import qualified Data.ByteString as ByteString -- | A 'Monad' that can also read input, either from standard input (STDIN) or -- from a file. class (Monad m) => MonadRead m where- -- | Reads input from the given file, or from STDIN if the given file is- -- 'Nothing'.- read :: Maybe FilePath -> m ByteString.ByteString+ -- | Reads input from the given 'Input.Input'.+ read :: Input.Input -> m ByteString.ByteString -- | Uses 'ByteString.getContents' or 'ByteString.readFile'. instance MonadRead IO where- read = maybe ByteString.getContents ByteString.readFile+ read i = case i of+ Input.Stdin -> ByteString.getContents+ Input.File f -> ByteString.readFile f
source/library/CabalGild/Class/MonadWrite.hs view
@@ -1,14 +1,16 @@ module CabalGild.Class.MonadWrite where +import qualified CabalGild.Type.Output as Output import qualified Data.ByteString as ByteString -- | A 'Monad' that can also write output, either to standard output (STDOUT) -- or to a file. class (Monad m) => MonadWrite m where- -- | Writes output to the given file, or to STDOUT if the given file is- -- 'Nothing'.- write :: Maybe FilePath -> ByteString.ByteString -> m ()+ -- | Writes output to the given 'Output.Output'.+ write :: Output.Output -> ByteString.ByteString -> m () -- | Uses 'ByteString.putStr' or 'ByteString.writeFile'. instance MonadWrite IO where- write = maybe ByteString.putStr ByteString.writeFile+ write o = case o of+ Output.Stdout -> ByteString.putStr+ Output.File f -> ByteString.writeFile f
+ source/library/CabalGild/Exception/SpecifiedOutputWithCheckMode.hs view
@@ -0,0 +1,12 @@+module CabalGild.Exception.SpecifiedOutputWithCheckMode where++import qualified Control.Monad.Catch as Exception++-- | This exception is thrown when the user specifies the output while using+-- the check mode. In other words, when @--mode=check@ and @--output=anything@.+data SpecifiedOutputWithCheckMode+ = SpecifiedOutputWithCheckMode+ deriving (Eq, Show)++instance Exception.Exception SpecifiedOutputWithCheckMode where+ displayException = const "cannot use --output when --mode is check"
+ source/library/CabalGild/Exception/SpecifiedStdinWithFileInput.hs view
@@ -0,0 +1,13 @@+module CabalGild.Exception.SpecifiedStdinWithFileInput where++import qualified Control.Monad.Catch as Exception++-- | This exception is thrown when the user specifies the STDIN name while+-- using an input file. In other words, when @--input=file@ and+-- @--stdin=anything@.+data SpecifiedStdinWithFileInput+ = SpecifiedStdinWithFileInput+ deriving (Eq, Show)++instance Exception.Exception SpecifiedStdinWithFileInput where+ displayException = const "cannot use --stdin when --input is a file"
source/library/CabalGild/Main.hs view
@@ -17,17 +17,15 @@ import qualified CabalGild.Exception.CheckFailure as CheckFailure import qualified CabalGild.Exception.ParseError as ParseError import qualified CabalGild.Type.Config as Config+import qualified CabalGild.Type.Context as Context import qualified CabalGild.Type.Flag as Flag+import qualified CabalGild.Type.Input as Input import qualified CabalGild.Type.Mode as Mode import qualified Control.Monad as Monad import qualified Control.Monad.Catch as Exception import qualified Data.ByteString as ByteString import qualified Data.ByteString.Char8 as Latin1-import qualified Data.Maybe as Maybe-import qualified Data.Version as Version import qualified Distribution.Fields as Fields-import qualified Paths_cabal_gild as This-import qualified System.Console.GetOpt as GetOpt import qualified System.Environment as Environment import qualified System.Exit as Exit import qualified System.IO as IO@@ -37,9 +35,8 @@ -- thrown, they will be handled by 'onException'. defaultMain :: IO () defaultMain = Exception.handle onException $ do- name <- Environment.getProgName arguments <- Environment.getArgs- mainWith name arguments+ mainWith arguments -- | If the exception was an 'Exit.ExitCode', simply exit with that code. -- Otherwise handle exceptions by printing them to STDERR using@@ -62,46 +59,35 @@ MonadWalk.MonadWalk m, MonadWrite.MonadWrite m ) =>- String -> [String] -> m ()-mainWith name arguments = do+mainWith arguments = do flags <- Flag.fromArguments arguments config <- Config.fromFlags flags- let version = Version.showVersion This.version-- Monad.when (Config.help config) $ do- let header =- unlines- [ name <> " version " <> version,- "",- "<https://github.com/tfausak/cabal-gild>"- ]- MonadLog.log $ GetOpt.usageInfo header Flag.options- Exception.throwM Exit.ExitSuccess-- Monad.when (Config.version config) $ do- MonadLog.logLn version- Exception.throwM Exit.ExitSuccess+ context <- Context.fromConfig config - input <- MonadRead.read $ Config.input config+ let source = Context.input context+ input <- MonadRead.read source fields <- either (Exception.throwM . ParseError.ParseError) pure $ Fields.readFields input let csv = GetCabalVersion.fromFields fields comments = ExtractComments.fromByteString input+ path = case source of+ Input.Stdin -> Context.stdin context+ Input.File f -> f output <- ( StripBlanks.run Monad.>=> AttachComments.run Monad.>=> ReflowText.run csv Monad.>=> RemovePositions.run- Monad.>=> EvaluatePragmas.run (Maybe.fromMaybe (Config.stdin config) $ Config.input config)+ Monad.>=> EvaluatePragmas.run path Monad.>=> FormatFields.run csv Monad.>=> Render.run ) (fields, comments) - case Config.mode config of+ case Context.mode context of Mode.Check -> do -- The input might have CRLF ("\r\n", 0x0d 0x0a) line endings, but the -- output will always have LF line endings. For the purposes of the check@@ -114,4 +100,6 @@ inputLines = stripCR <$> Latin1.lines input Monad.when (outputLines /= inputLines) $ Exception.throwM CheckFailure.CheckFailure- Mode.Format -> MonadWrite.write (Config.output config) output+ Mode.Format -> do+ let target = Context.output context+ MonadWrite.write target output
source/library/CabalGild/Type/Config.hs view
@@ -2,19 +2,22 @@ module CabalGild.Type.Config where import qualified CabalGild.Type.Flag as Flag+import qualified CabalGild.Type.Input as Input import qualified CabalGild.Type.Mode as Mode+import qualified CabalGild.Type.Optional as Optional+import qualified CabalGild.Type.Output as Output import qualified Control.Monad as Monad import qualified Control.Monad.Catch as Exception -- | This data type represents the configuration for the command line utility. -- Each field typically corresponds to a flag. data Config = Config- { help :: Bool,- input :: Maybe FilePath,- mode :: Mode.Mode,- output :: Maybe FilePath,- stdin :: FilePath,- version :: Bool+ { help :: Optional.Optional Bool,+ input :: Optional.Optional Input.Input,+ mode :: Optional.Optional Mode.Mode,+ output :: Optional.Optional Output.Output,+ stdin :: Optional.Optional FilePath,+ version :: Optional.Optional Bool } deriving (Eq, Show) @@ -22,29 +25,25 @@ initial :: Config initial = Config- { help = False,- input = Nothing,- mode = Mode.Format,- output = Nothing,- stdin = ".",- version = False+ { help = Optional.Default,+ input = Optional.Default,+ mode = Optional.Default,+ output = Optional.Default,+ stdin = Optional.Default,+ version = Optional.Default } -- | Applies a flag to the config, returning the new config. applyFlag :: (Exception.MonadThrow m) => Config -> Flag.Flag -> m Config applyFlag config flag = case flag of- Flag.Help b -> pure config {help = b}- Flag.Input s -> case s of- "-" -> pure config {input = Nothing}- _ -> pure config {input = Just s}+ Flag.Help b -> pure config {help = Optional.Specific b}+ Flag.Input s -> pure config {input = Optional.Specific $ Input.fromString s} Flag.Mode s -> do m <- Mode.fromString s- pure config {mode = m}- Flag.Output s -> case s of- "-" -> pure config {output = Nothing}- _ -> pure config {output = Just s}- Flag.Stdin s -> pure config {stdin = s}- Flag.Version b -> pure config {version = b}+ pure config {mode = Optional.Specific m}+ Flag.Output s -> pure config {output = Optional.Specific $ Output.fromString s}+ Flag.Stdin s -> pure config {stdin = Optional.Specific s}+ Flag.Version b -> pure config {version = Optional.Specific b} -- | Converts a list of flags into a config by starting with 'initial' and -- repeatedly calling 'applyFlag'.
+ source/library/CabalGild/Type/Context.hs view
@@ -0,0 +1,73 @@+module CabalGild.Type.Context where++import qualified CabalGild.Class.MonadLog as MonadLog+import qualified CabalGild.Exception.SpecifiedOutputWithCheckMode as SpecifiedOutputWithCheckMode+import qualified CabalGild.Exception.SpecifiedStdinWithFileInput as SpecifiedStdinWithFileInput+import qualified CabalGild.Type.Config as Config+import qualified CabalGild.Type.Flag as Flag+import qualified CabalGild.Type.Input as Input+import qualified CabalGild.Type.Mode as Mode+import qualified CabalGild.Type.Optional as Optional+import qualified CabalGild.Type.Output as Output+import qualified Control.Monad as Monad+import qualified Control.Monad.Catch as Exception+import qualified Data.Char as Char+import qualified Data.List as List+import qualified Data.Version as Version+import qualified Paths_cabal_gild as This+import qualified System.Console.GetOpt as GetOpt+import qualified System.Exit as Exit++-- | Represents the context necessary to run the program. This is essentially a+-- simplified 'Config.Config'.+data Context = Context+ { input :: Input.Input,+ mode :: Mode.Mode,+ output :: Output.Output,+ stdin :: FilePath+ }+ deriving (Eq, Show)++-- | Creates a 'Context' from a 'Config.Config'. If the help or version was+-- requested, then this will throw an 'Exit.ExitSuccess'. Otherwise this makes+-- sure the config is valid before returning the context.+fromConfig ::+ (MonadLog.MonadLog m, Exception.MonadThrow m) =>+ Config.Config ->+ m Context+fromConfig config = do+ let version = Version.showVersion This.version++ Monad.when (Optional.withDefault False $ Config.help config) $ do+ let header =+ unlines+ [ "cabal-gild version " <> version,+ "",+ "<https://github.com/tfausak/cabal-gild>"+ ]+ MonadLog.logLn+ . List.dropWhileEnd Char.isSpace+ $ GetOpt.usageInfo header Flag.options+ Exception.throwM Exit.ExitSuccess++ Monad.when (Optional.withDefault False $ Config.version config) $ do+ MonadLog.logLn version+ Exception.throwM Exit.ExitSuccess++ case (Config.input config, Config.stdin config) of+ (Optional.Specific (Input.File _), Optional.Specific _) ->+ Exception.throwM SpecifiedStdinWithFileInput.SpecifiedStdinWithFileInput+ _ -> pure ()++ case (Config.mode config, Config.output config) of+ (Optional.Specific Mode.Check, Optional.Specific _) ->+ Exception.throwM SpecifiedOutputWithCheckMode.SpecifiedOutputWithCheckMode+ _ -> pure ()++ pure+ Context+ { input = Optional.withDefault Input.Stdin $ Config.input config,+ mode = Optional.withDefault Mode.Format $ Config.mode config,+ output = Optional.withDefault Output.Stdout $ Config.output config,+ stdin = Optional.withDefault "." $ Config.stdin config+ }
+ source/library/CabalGild/Type/Input.hs view
@@ -0,0 +1,15 @@+module CabalGild.Type.Input where++-- | Represents an input stream, which can either be standard input (STDIN) or+-- a file.+data Input+ = Stdin+ | File FilePath+ deriving (Eq, Ord, Show)++-- | Converts a string into an input. The string @"-"@ will be converted into+-- 'Stdin', and any other string will be converted into 'File'.+fromString :: String -> Input+fromString s = case s of+ "-" -> Stdin+ _ -> File s
+ source/library/CabalGild/Type/Optional.hs view
@@ -0,0 +1,20 @@+module CabalGild.Type.Optional where++-- | Represents a value that may or may not be present. Isomorphic to 'Maybe'.+-- Useful to distinguish between a value not being given and a value happening+-- to be the same as the default.+data Optional a+ = Default+ | Specific a+ deriving (Eq, Show)++-- | Uses the provided default value if the optional is 'Default', otherwise+-- gets the value out of the 'Specific'. Similar to 'Data.Maybe.fromMaybe'.+withDefault :: a -> Optional a -> a+withDefault = flip optional id++-- | Basic destructor, similar to 'maybe'.+optional :: b -> (a -> b) -> Optional a -> b+optional b f o = case o of+ Default -> b+ Specific s -> f s
+ source/library/CabalGild/Type/Output.hs view
@@ -0,0 +1,15 @@+module CabalGild.Type.Output where++-- | Represents an output stream, which can either be standard output+-- (STDOUT) or a file.+data Output+ = Stdout+ | File FilePath+ deriving (Eq, Ord, Show)++-- | Converts a string into an output. The string @"-"@ will be converted into+-- 'Stdout', and any other string will be converted into 'File'.+fromString :: String -> Output+fromString s = case s of+ "-" -> Stdout+ _ -> File s
source/test-suite/Main.hs view
@@ -4,18 +4,23 @@ import qualified CabalGild.Class.MonadRead as MonadRead import qualified CabalGild.Class.MonadWalk as MonadWalk import qualified CabalGild.Class.MonadWrite as MonadWrite+import qualified CabalGild.Exception.CheckFailure as CheckFailure+import qualified CabalGild.Exception.SpecifiedOutputWithCheckMode as SpecifiedOutputWithCheckMode+import qualified CabalGild.Exception.SpecifiedStdinWithFileInput as SpecifiedStdinWithFileInput import qualified CabalGild.Extra.String as String import qualified CabalGild.Main as Gild+import qualified CabalGild.Type.Input as Input+import qualified CabalGild.Type.Output as Output import qualified Control.Monad.Catch as Exception import qualified Control.Monad.Trans.Class as Trans import qualified Control.Monad.Trans.Except as ExceptT import qualified Control.Monad.Trans.RWS as RWST import qualified Data.ByteString as ByteString-import qualified Data.Either as Either import qualified Data.Function as Function import qualified Data.Functor.Identity as Identity import qualified Data.Map as Map import qualified GHC.Stack as Stack+import qualified System.Exit as Exit import qualified System.FilePath as FilePath import qualified Test.Hspec as Hspec @@ -24,48 +29,48 @@ Hspec.it "shows the help" $ do let (a, s, w) = runTest- (Gild.mainWith "" ["--help"])+ (Gild.mainWith ["--help"]) (Map.empty, Map.empty) Map.empty- a `Hspec.shouldSatisfy` Either.isLeft+ a `Hspec.shouldBe` Left (Problem $ Exception.toException Exit.ExitSuccess) w `Hspec.shouldNotSatisfy` null s `Hspec.shouldBe` Map.empty Hspec.it "shows the version" $ do let (a, s, w) = runTest- (Gild.mainWith "" ["--version"])+ (Gild.mainWith ["--version"]) (Map.empty, Map.empty) Map.empty- a `Hspec.shouldSatisfy` Either.isLeft+ a `Hspec.shouldBe` Left (Problem $ Exception.toException Exit.ExitSuccess) w `Hspec.shouldNotSatisfy` null s `Hspec.shouldBe` Map.empty Hspec.it "reads from an input file" $ do let (a, s, w) = runTest- (Gild.mainWith "" ["--input", "input.cabal"])- (Map.singleton (Just "input.cabal") (String.toUtf8 ""), Map.empty)+ (Gild.mainWith ["--input", "input.cabal"])+ (Map.singleton (Input.File "input.cabal") (String.toUtf8 ""), Map.empty) Map.empty a `Hspec.shouldBe` Right () w `Hspec.shouldBe` []- s `Hspec.shouldSatisfy` Map.member Nothing+ s `Hspec.shouldSatisfy` Map.member Output.Stdout Hspec.it "writes to an output file" $ do let (a, s, w) = runTest- (Gild.mainWith "" ["--output", "output.cabal"])- (Map.singleton Nothing (String.toUtf8 ""), Map.empty)+ (Gild.mainWith ["--output", "output.cabal"])+ (Map.singleton Input.Stdin (String.toUtf8 ""), Map.empty) Map.empty a `Hspec.shouldBe` Right () w `Hspec.shouldBe` []- s `Hspec.shouldSatisfy` Map.member (Just "output.cabal")+ s `Hspec.shouldSatisfy` Map.member (Output.File "output.cabal") Hspec.it "succeeds when checking formatted input" $ do let (a, s, w) = runTest- (Gild.mainWith "" ["--mode", "check"])- (Map.singleton Nothing (String.toUtf8 ""), Map.empty)+ (Gild.mainWith ["--mode", "check"])+ (Map.singleton Input.Stdin (String.toUtf8 ""), Map.empty) Map.empty a `Hspec.shouldBe` Right () w `Hspec.shouldBe` []@@ -74,23 +79,43 @@ Hspec.it "fails when checking unformatted input" $ do let (a, s, w) = runTest- (Gild.mainWith "" ["--mode", "check"])- (Map.singleton Nothing (String.toUtf8 "fail:yes"), Map.empty)+ (Gild.mainWith ["--mode", "check"])+ (Map.singleton Input.Stdin (String.toUtf8 "fail:yes"), Map.empty) Map.empty- a `Hspec.shouldSatisfy` Either.isLeft+ a `Hspec.shouldBe` Left (Problem $ Exception.toException CheckFailure.CheckFailure) w `Hspec.shouldBe` [] s `Hspec.shouldBe` Map.empty Hspec.it "succeeds when checking CRLF input" $ do let (a, s, w) = runTest- (Gild.mainWith "" ["--mode", "check"])- (Map.singleton Nothing (String.toUtf8 "pass: yes\r\n"), Map.empty)+ (Gild.mainWith ["--mode", "check"])+ (Map.singleton Input.Stdin (String.toUtf8 "pass: yes\r\n"), Map.empty) Map.empty a `Hspec.shouldBe` Right () w `Hspec.shouldBe` [] s `Hspec.shouldBe` Map.empty + Hspec.it "fails when --stdin is given with an input file" $ do+ let (a, s, w) =+ runTest+ (Gild.mainWith ["--input", "f", "--stdin", "g"])+ (Map.empty, Map.empty)+ Map.empty+ a `Hspec.shouldBe` Left (Problem $ Exception.toException SpecifiedStdinWithFileInput.SpecifiedStdinWithFileInput)+ w `Hspec.shouldBe` []+ s `Hspec.shouldBe` Map.empty++ Hspec.it "fails when --output is given with check mode" $ do+ let (a, s, w) =+ runTest+ (Gild.mainWith ["--mode", "check", "--output", "-"])+ (Map.empty, Map.empty)+ Map.empty+ a `Hspec.shouldBe` Left (Problem $ Exception.toException SpecifiedOutputWithCheckMode.SpecifiedOutputWithCheckMode)+ w `Hspec.shouldBe` []+ s `Hspec.shouldBe` Map.empty+ Hspec.it "succeeds with empty input" $ do expectGilded ""@@ -949,13 +974,13 @@ expectGilded input expected = do let (a, s, w) = runTest- (Gild.mainWith "" [])- (Map.singleton Nothing $ String.toUtf8 input, Map.empty)+ (Gild.mainWith [])+ (Map.singleton Input.Stdin $ String.toUtf8 input, Map.empty) Map.empty a `Hspec.shouldBe` Right () w `Hspec.shouldBe` [] actual <- case Map.toList s of- [(Nothing, x)] -> pure x+ [(Output.Stdout, x)] -> pure x _ -> fail $ "impossible: " <> show s actual `Hspec.shouldBe` String.toUtf8 expected -- After formatting, the output should not change if we format it again.@@ -965,13 +990,13 @@ expectStable input = do let (a, s, w) = runTest- (Gild.mainWith "" [])- (Map.singleton Nothing input, Map.empty)+ (Gild.mainWith [])+ (Map.singleton Input.Stdin input, Map.empty) Map.empty a `Hspec.shouldBe` Right () w `Hspec.shouldBe` [] output <- case Map.toList s of- [(Nothing, x)] -> pure x+ [(Output.Stdout, x)] -> pure x _ -> fail $ "impossible: " <> show s output `Hspec.shouldBe` input @@ -979,15 +1004,15 @@ expectDiscover files input expected = do let (a, s, w) = runTest- (Gild.mainWith "" [])- ( Map.singleton Nothing $ String.toUtf8 input,+ (Gild.mainWith [])+ ( Map.singleton Input.Stdin $ String.toUtf8 input, Map.fromList $ fmap (\(d, fs) -> (d, FilePath.combine d <$> fs)) files ) Map.empty a `Hspec.shouldBe` Right () w `Hspec.shouldBe` [] actual <- case Map.toList s of- [(Nothing, x)] -> pure x+ [(Output.Stdout, x)] -> pure x _ -> fail $ "impossible: " <> show s actual `Hspec.shouldBe` String.toUtf8 expected @@ -1006,9 +1031,9 @@ type E = Problem -type R = (S, Map.Map FilePath [FilePath])+type R = (Map.Map Input.Input ByteString.ByteString, Map.Map FilePath [FilePath]) -type S = Map.Map (Maybe FilePath) ByteString.ByteString+type S = Map.Map Output.Output ByteString.ByteString type W = [String] @@ -1018,7 +1043,7 @@ deriving (Applicative, Functor, Monad) instance (Monad m) => MonadLog.MonadLog (TestT m) where- log = TestT . Trans.lift . RWST.tell . pure+ logLn = TestT . Trans.lift . RWST.tell . pure instance (Monad m) => MonadRead.MonadRead (TestT m) where read k = do