cabal-gild 1.8.2.1 → 1.8.3.0
raw patch · 9 files changed
+303/−109 lines, 9 filesPVP: major bump suggested
API removals or changes: PVP suggests a major version bump
API changes (from Hackage documentation)
- CabalGild.Unstable.Exception.UnexpectedArgument: UnexpectedArgument :: String -> UnexpectedArgument
- CabalGild.Unstable.Exception.UnexpectedArgument: fromString :: String -> UnexpectedArgument
- CabalGild.Unstable.Exception.UnexpectedArgument: instance GHC.Classes.Eq CabalGild.Unstable.Exception.UnexpectedArgument.UnexpectedArgument
- CabalGild.Unstable.Exception.UnexpectedArgument: instance GHC.Internal.Exception.Type.Exception CabalGild.Unstable.Exception.UnexpectedArgument.UnexpectedArgument
- CabalGild.Unstable.Exception.UnexpectedArgument: instance GHC.Internal.Show.Show CabalGild.Unstable.Exception.UnexpectedArgument.UnexpectedArgument
- CabalGild.Unstable.Exception.UnexpectedArgument: newtype UnexpectedArgument
+ CabalGild.Unstable.Exception.MixedArgumentStyles: MixedArgumentStyles :: String -> MixedArgumentStyles
+ CabalGild.Unstable.Exception.MixedArgumentStyles: instance GHC.Classes.Eq CabalGild.Unstable.Exception.MixedArgumentStyles.MixedArgumentStyles
+ CabalGild.Unstable.Exception.MixedArgumentStyles: instance GHC.Internal.Exception.Type.Exception CabalGild.Unstable.Exception.MixedArgumentStyles.MixedArgumentStyles
+ CabalGild.Unstable.Exception.MixedArgumentStyles: instance GHC.Internal.Show.Show CabalGild.Unstable.Exception.MixedArgumentStyles.MixedArgumentStyles
+ CabalGild.Unstable.Exception.MixedArgumentStyles: newtype MixedArgumentStyles
+ CabalGild.Unstable.Main: processFile :: (MonadRead m, MonadThrow m, MonadWalk m, MonadWarn m, MonadWrite m) => Context -> FilePath -> m ()
+ CabalGild.Unstable.Main: processFiles :: (MonadRead m, MonadCatch m, MonadWalk m, MonadWarn m, MonadWrite m) => Context -> [FilePath] -> m ()
+ CabalGild.Unstable.Main: processOne :: (MonadRead m, MonadThrow m, MonadWalk m, MonadWarn m, MonadWrite m) => Context -> m ()
+ CabalGild.Unstable.Type.Config: [files] :: Config -> [FilePath]
- CabalGild: mainWith :: (MonadHandle m, MonadLog m, MonadRead m, MonadThrow m, MonadWalk m, MonadWarn m, MonadWrite m) => [String] -> m ()
+ CabalGild: mainWith :: (MonadHandle m, MonadLog m, MonadRead m, MonadCatch m, MonadWalk m, MonadWarn m, MonadWrite m) => [String] -> m ()
- CabalGild.Unstable.Main: mainWith :: (MonadHandle m, MonadLog m, MonadRead m, MonadThrow m, MonadWalk m, MonadWarn m, MonadWrite m) => [String] -> m ()
+ CabalGild.Unstable.Main: mainWith :: (MonadHandle m, MonadLog m, MonadRead m, MonadCatch m, MonadWalk m, MonadWarn m, MonadWrite m) => [String] -> m ()
- CabalGild.Unstable.Type.Config: Config :: Optional Leniency -> Optional Bool -> Optional Input -> Optional Mode -> Optional Output -> Optional FilePath -> Optional Bool -> Config
+ CabalGild.Unstable.Type.Config: Config :: Optional Leniency -> [FilePath] -> Optional Bool -> Optional Input -> Optional Mode -> Optional Output -> Optional FilePath -> Optional Bool -> Config
- CabalGild.Unstable.Type.Config: fromFlags :: MonadThrow m => [Flag] -> m Config
+ CabalGild.Unstable.Type.Config: fromFlags :: MonadThrow m => [Flag] -> [String] -> m Config
- CabalGild.Unstable.Type.Context: fromConfig :: (MonadHandle m, MonadLog m, MonadThrow m, MonadWalk m) => Config -> m Context
+ CabalGild.Unstable.Type.Context: fromConfig :: (MonadHandle m, MonadLog m, MonadWarn m, MonadThrow m, MonadWalk m) => Config -> m Context
- CabalGild.Unstable.Type.Flag: fromArguments :: MonadThrow m => [String] -> m [Flag]
+ CabalGild.Unstable.Type.Flag: fromArguments :: MonadThrow m => [String] -> m ([Flag], [String])
Files
- README.md +35/−24
- cabal-gild.cabal +2/−2
- source/library/CabalGild/Unstable/Exception/MixedArgumentStyles.hs +13/−0
- source/library/CabalGild/Unstable/Exception/UnexpectedArgument.hs +0/−16
- source/library/CabalGild/Unstable/Main.hs +61/−3
- source/library/CabalGild/Unstable/Type/Config.hs +6/−2
- source/library/CabalGild/Unstable/Type/Context.hs +26/−2
- source/library/CabalGild/Unstable/Type/Flag.hs +7/−9
- source/test-suite/Main.hs +153/−51
README.md view
@@ -117,10 +117,24 @@ ## Usage -Gild is a command line utility named `cabal-gild`. By default it reads from-standard input (STDIN) and writes to standard output (STDOUT). Its behavior can-be modified with command line options, which are described below.+Gild is a command line utility named `cabal-gild`. Pass one or more files as+arguments to format them in-place: +``` sh+$ cabal-gild p.cabal+$ cabal-gild a.cabal b.cabal+```++When no files are given, Gild reads from standard input (STDIN) and writes to+standard output (STDOUT):++``` sh+$ cabal-gild < p.cabal > q.cabal+```++When run interactively with no arguments, Gild will look for a `*.cabal` file+in the current directory and format it in-place.+ ### Options Run `cabal-gild --help` to see the options that Gild supports. They are:@@ -136,30 +150,12 @@ to the expected output. (Note that Gild will never produce CRLF line endings when formatting.) -- `--input=FILE`: Uses `FILE` as the input. If this is `-` (which is the- default), then the input will be read from STDIN.--- `--io=FILE`: Shortcut for setting both `--input=FILE` and `--output=FILE` at- the same time. This is useful for formatting a file in-place.- - `--mode=MODE`: Sets the mode to `MODE`, which must be either `format` (the default) or `check`. When the mode is `format`, Gild will output the formatted package description. When the mode is `check`, Gild will exit successfully if the input is already formatted, otherwise it will exit- unsuccessfully.--- `--output=FILE`: Uses `FILE` as the output. If this is `-` (which is the- default), then the output will be written to STDOUT. To modify a file in- place, use the same file as both input and output. For example:-- ``` sh- $ cabal-gild --input p.cabal --output p.cabal- ```-- If the output is the same file as the input and the input is already- formatted, then nothing will happen. The output will not be modified.-- It is an error to provide a value for this option when the mode is `check`.+ unsuccessfully. When checking multiple files, all files are checked before+ exiting. - `--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@@ -169,7 +165,22 @@ $ cabal-gild --stdin p.cabal < p.cabal ``` - It is an error to provide a value for this option unless the input is `-`.+ It is an error to provide a value for this option when a file argument is+ given.++### Deprecated Options++The following options are deprecated and will be removed in a future version.+Use positional file arguments instead.++- `--input=FILE`: Uses `FILE` as the input. Use a positional argument instead.++- `--output=FILE`: Uses `FILE` as the output. Use piping instead.++- `--io=FILE`: Shortcut for setting both `--input` and `--output`. Use a+ positional argument instead.++It is an error to combine these options with positional file arguments. ### Pragmas
cabal-gild.cabal view
@@ -11,7 +11,7 @@ maintainer: Taylor Fausak name: cabal-gild synopsis: Formats package descriptions.-version: 1.8.2.1+version: 1.8.3.0 source-repository head type: git@@ -90,12 +90,12 @@ CabalGild.Unstable.Exception.InvalidLeniency CabalGild.Unstable.Exception.InvalidMode CabalGild.Unstable.Exception.InvalidOption+ CabalGild.Unstable.Exception.MixedArgumentStyles CabalGild.Unstable.Exception.MoreThanOneCabalFileFound CabalGild.Unstable.Exception.NoCabalFileFound CabalGild.Unstable.Exception.ParseError CabalGild.Unstable.Exception.SpecifiedOutputWithCheckMode CabalGild.Unstable.Exception.SpecifiedStdinWithFileInput- CabalGild.Unstable.Exception.UnexpectedArgument CabalGild.Unstable.Exception.UnknownOption CabalGild.Unstable.Exception.UnsatisfiedRequire CabalGild.Unstable.Extra.ByteString
+ source/library/CabalGild/Unstable/Exception/MixedArgumentStyles.hs view
@@ -0,0 +1,13 @@+module CabalGild.Unstable.Exception.MixedArgumentStyles where++import qualified Control.Monad.Catch as Exception++-- | This exception is thrown when positional file arguments are used together+-- with the deprecated @--input@, @--output@, or @--io@ flags.+newtype MixedArgumentStyles+ = MixedArgumentStyles String+ deriving (Eq, Show)++instance Exception.Exception MixedArgumentStyles where+ displayException (MixedArgumentStyles opt) =+ "cannot use --" <> opt <> " with positional file arguments"
− source/library/CabalGild/Unstable/Exception/UnexpectedArgument.hs
@@ -1,16 +0,0 @@-module CabalGild.Unstable.Exception.UnexpectedArgument where--import qualified Control.Monad.Catch as Exception---- | This exception is thrown when an unexpected command line argument is--- encountered.-newtype UnexpectedArgument- = UnexpectedArgument String- deriving (Eq, Show)--instance Exception.Exception UnexpectedArgument where- displayException (UnexpectedArgument s) = "unexpected argument: " <> s---- | Constructs an 'UnexpectedArgument' from the given 'String'.-fromString :: String -> UnexpectedArgument-fromString = UnexpectedArgument
source/library/CabalGild/Unstable/Main.hs view
@@ -1,3 +1,5 @@+{-# LANGUAGE ScopedTypeVariables #-}+ -- | This module defines the main entry point for the application. module CabalGild.Unstable.Main where @@ -59,7 +61,7 @@ ( MonadHandle.MonadHandle m, MonadLog.MonadLog m, MonadRead.MonadRead m,- Exception.MonadThrow m,+ Exception.MonadCatch m, MonadWalk.MonadWalk m, MonadWarn.MonadWarn m, MonadWrite.MonadWrite m@@ -67,10 +69,66 @@ [String] -> m () mainWith arguments = do- flags <- Flag.fromArguments arguments- config <- Config.fromFlags flags+ (flags, positionalArgs) <- Flag.fromArguments arguments+ config <- Config.fromFlags flags positionalArgs context <- Context.fromConfig config + case Config.files config of+ [] -> processOne context+ fps -> processFiles context fps++processFiles ::+ forall m.+ ( MonadRead.MonadRead m,+ Exception.MonadCatch m,+ MonadWalk.MonadWalk m,+ MonadWarn.MonadWarn m,+ MonadWrite.MonadWrite m+ ) =>+ Context.Context ->+ [FilePath] ->+ m ()+processFiles context = go False+ where+ go :: Bool -> [FilePath] -> m ()+ go anyFail [] =+ Monad.when anyFail $ Exception.throwM CheckFailure.CheckFailure+ go anyFail (fp : fps) = do+ result <- Exception.try (processFile context fp)+ let anyFail' = case (result :: Either CheckFailure.CheckFailure ()) of+ Left _ -> True+ Right _ -> anyFail+ go anyFail' fps++processFile ::+ ( MonadRead.MonadRead m,+ Exception.MonadThrow m,+ MonadWalk.MonadWalk m,+ MonadWarn.MonadWarn m,+ MonadWrite.MonadWrite m+ ) =>+ Context.Context ->+ FilePath ->+ m ()+processFile context fp =+ let ctx =+ context+ { Context.input = Input.File fp,+ Context.output = Output.File fp,+ Context.stdin = fp+ }+ in processOne ctx++processOne ::+ ( MonadRead.MonadRead m,+ Exception.MonadThrow m,+ MonadWalk.MonadWalk m,+ MonadWarn.MonadWarn m,+ MonadWrite.MonadWrite m+ ) =>+ Context.Context ->+ m ()+processOne context = do input <- MonadRead.read $ Context.input context output <- format (Context.stdin context) input
source/library/CabalGild/Unstable/Type/Config.hs view
@@ -14,6 +14,7 @@ -- Each field typically corresponds to a flag. data Config = Config { crlf :: Optional.Optional Leniency.Leniency,+ files :: [FilePath], help :: Optional.Optional Bool, input :: Optional.Optional Input.Input, mode :: Optional.Optional Mode.Mode,@@ -28,6 +29,7 @@ initial = Config { crlf = Optional.Default,+ files = [], help = Optional.Default, input = Optional.Default, mode = Optional.Default,@@ -59,5 +61,7 @@ -- | Converts a list of flags into a config by starting with 'initial' and -- repeatedly calling 'applyFlag'.-fromFlags :: (Exception.MonadThrow m) => [Flag.Flag] -> m Config-fromFlags = Monad.foldM applyFlag initial+fromFlags :: (Exception.MonadThrow m) => [Flag.Flag] -> [String] -> m Config+fromFlags flags args = do+ config <- Monad.foldM applyFlag initial flags+ pure config {files = args}
source/library/CabalGild/Unstable/Type/Context.hs view
@@ -3,6 +3,8 @@ import qualified CabalGild.Unstable.Class.MonadHandle as MonadHandle import qualified CabalGild.Unstable.Class.MonadLog as MonadLog import qualified CabalGild.Unstable.Class.MonadWalk as MonadWalk+import qualified CabalGild.Unstable.Class.MonadWarn as MonadWarn+import qualified CabalGild.Unstable.Exception.MixedArgumentStyles as MixedArgumentStyles import qualified CabalGild.Unstable.Exception.MoreThanOneCabalFileFound as MoreThanOneCabalFileFound import qualified CabalGild.Unstable.Exception.NoCabalFileFound as NoCabalFileFound import qualified CabalGild.Unstable.Exception.SpecifiedOutputWithCheckMode as SpecifiedOutputWithCheckMode@@ -42,6 +44,7 @@ fromConfig :: ( MonadHandle.MonadHandle m, MonadLog.MonadLog m,+ MonadWarn.MonadWarn m, Exception.MonadThrow m, MonadWalk.MonadWalk m ) =>@@ -55,7 +58,9 @@ unlines [ "cabal-gild version " <> version, "",- "<https://github.com/tfausak/cabal-gild>"+ "<https://github.com/tfausak/cabal-gild>",+ "",+ "Usage: cabal-gild [OPTIONS] [FILE ...]" ] MonadLog.logLn . List.dropWhileEnd Char.isSpace@@ -66,6 +71,25 @@ MonadLog.logLn version Exception.throwM Exit.ExitSuccess + case (Config.files config, Config.input config, Config.output config) of+ (_ : _, Optional.Specific _, _) ->+ Exception.throwM $ MixedArgumentStyles.MixedArgumentStyles Flag.inputOption+ (_ : _, _, Optional.Specific _) ->+ Exception.throwM $ MixedArgumentStyles.MixedArgumentStyles Flag.outputOption+ ([], Optional.Specific _, Optional.Specific _) -> do+ MonadWarn.warnLn "warning: --input is deprecated, use a positional argument instead"+ MonadWarn.warnLn "warning: --output is deprecated, use piping instead"+ ([], Optional.Specific _, _) ->+ MonadWarn.warnLn "warning: --input is deprecated, use a positional argument instead"+ ([], _, Optional.Specific _) ->+ MonadWarn.warnLn "warning: --output is deprecated, use piping instead"+ _ -> pure ()++ case (Config.files config, Config.stdin config) of+ (_ : _, Optional.Specific _) ->+ Exception.throwM $ MixedArgumentStyles.MixedArgumentStyles Flag.stdinOption+ _ -> pure ()+ case (Config.input config, Config.stdin config) of (Optional.Specific (Input.File _), Optional.Specific _) -> Exception.throwM SpecifiedStdinWithFileInput.SpecifiedStdinWithFileInput@@ -83,7 +107,7 @@ preOutput = Maybe.fromMaybe Output.Stdout . Optional.toMaybe $ Config.output config (theInput, theOutput) <- do isTerm <- MonadHandle.isTerminalDevice IO.stdin- if preInput == Input.Stdin && preOutput == Output.Stdout && isTerm+ if null (Config.files config) && preInput == Input.Stdin && preOutput == Output.Stdout && isTerm then do cabalFiles <- MonadWalk.walk "." ["*.cabal"] [] case cabalFiles of
source/library/CabalGild/Unstable/Type/Flag.hs view
@@ -2,7 +2,6 @@ import qualified CabalGild.Unstable.Exception.DuplicateOption as DuplicateOption import qualified CabalGild.Unstable.Exception.InvalidOption as InvalidOption-import qualified CabalGild.Unstable.Exception.UnexpectedArgument as UnexpectedArgument import qualified CabalGild.Unstable.Exception.UnknownOption as UnknownOption import qualified Control.Monad.Catch as Exception import qualified Data.Foldable as Foldable@@ -56,12 +55,12 @@ ['i'] [inputOption] (GetOpt.ReqArg Input "FILE")- "Sets the input file. Use '-' for standard input (STDIN).\nDefault: '-'",+ "Deprecated. Sets the input file. Use a positional argument instead.", GetOpt.Option [] [ioOption] (GetOpt.ReqArg IO "FILE")- "Shortcut for setting both the input and output files.",+ "Deprecated. Shortcut for setting both the input and output files.\nUse a positional argument instead.", GetOpt.Option ['m'] [modeOption]@@ -71,7 +70,7 @@ ['o'] [outputOption] (GetOpt.ReqArg Output "FILE")- "Sets the output file. Use '-' for standard output (STDOUT).\nDefault: '-'",+ "Deprecated. Sets the output file. Use piping instead.", GetOpt.Option ['s'] [stdinOption]@@ -97,17 +96,16 @@ stdinOption :: String stdinOption = "stdin" --- | Converts a list of command line arguments into a list of flags. If there--- are any unexpected arguments, invalid options, or unknown options, an+-- | Converts a list of command line arguments into a list of flags and+-- positional arguments. If there are any invalid options or unknown options, an -- exception will be thrown.-fromArguments :: (Exception.MonadThrow m) => [String] -> m [Flag]+fromArguments :: (Exception.MonadThrow m) => [String] -> m ([Flag], [String]) fromArguments arguments = do let (flgs, args, opts, errs) = GetOpt.getOpt' GetOpt.Permute options arguments- Foldable.traverse_ (Exception.throwM . UnexpectedArgument.fromString) args Foldable.traverse_ (Exception.throwM . InvalidOption.fromString) errs Foldable.traverse_ (Exception.throwM . UnknownOption.fromString) opts detectDuplicateOptions flgs- pure flgs+ pure (flgs, args) detectDuplicateOptions :: (Exception.MonadThrow m) => [Flag] -> m () detectDuplicateOptions =
source/test-suite/Main.hs view
@@ -10,11 +10,11 @@ import qualified CabalGild.Unstable.Exception.CheckFailure as CheckFailure import qualified CabalGild.Unstable.Exception.DuplicateOption as DuplicateOption import qualified CabalGild.Unstable.Exception.InvalidOption as InvalidOption+import qualified CabalGild.Unstable.Exception.MixedArgumentStyles as MixedArgumentStyles import qualified CabalGild.Unstable.Exception.MoreThanOneCabalFileFound as MoreThanOneCabalFileFound import qualified CabalGild.Unstable.Exception.NoCabalFileFound as NoCabalFileFound import qualified CabalGild.Unstable.Exception.SpecifiedOutputWithCheckMode as SpecifiedOutputWithCheckMode import qualified CabalGild.Unstable.Exception.SpecifiedStdinWithFileInput as SpecifiedStdinWithFileInput-import qualified CabalGild.Unstable.Exception.UnexpectedArgument as UnexpectedArgument import qualified CabalGild.Unstable.Exception.UnknownOption as UnknownOption import qualified CabalGild.Unstable.Extra.String as String import qualified CabalGild.Unstable.Main as Gild@@ -59,9 +59,15 @@ expectException ["--help=invalid"] $ InvalidOption.fromString "option `--help' doesn't allow an argument" - Hspec.it "fails with an unexpected argument" $ do- expectException ["unexpected"] $- UnexpectedArgument.fromString "unexpected"+ Hspec.it "accepts a positional argument" $ do+ let (a, s, _w) =+ runGild+ ["p.cabal"]+ [(Input.File "p.cabal", String.toUtf8 "")]+ (".", [])+ False+ a `Hspec.shouldSatisfy` Either.isRight+ s `Hspec.shouldBe` Map.empty Hspec.it "fails when --crlf is given twice" $ do expectException ["--crlf=strict", "--crlf=lenient"] $@@ -102,16 +108,16 @@ ["--stdin=f", "--stdin=g"] $ DuplicateOption.DuplicateOption "stdin" "f" "g" - Hspec.it "reads from an input file" $ do+ Hspec.it "formats a positional file in-place" $ do let (a, s, w) = runGild- ["--input", "input.cabal"]+ ["input.cabal"] [(Input.File "input.cabal", String.toUtf8 "")] (".", []) False a `Hspec.shouldSatisfy` Either.isRight w `Hspec.shouldBe` []- s `Hspec.shouldBe` Map.singleton Output.Stdout (String.toUtf8 "")+ s `Hspec.shouldBe` Map.empty Hspec.it "writes to an output file" $ do let (a, s, w) =@@ -121,7 +127,7 @@ (".", []) False a `Hspec.shouldSatisfy` Either.isRight- w `Hspec.shouldBe` []+ w `Hspec.shouldBe` ["warning: --output is deprecated, use piping instead"] s `Hspec.shouldBe` Map.singleton (Output.File "output.cabal") (String.toUtf8 "") Hspec.it "succeeds when checking formatted input" $ do@@ -176,7 +182,7 @@ (".", []) False a `shouldBeFailure` SpecifiedStdinWithFileInput.SpecifiedStdinWithFileInput- w `Hspec.shouldBe` []+ w `Hspec.shouldBe` ["warning: --input is deprecated, use a positional argument instead"] s `Hspec.shouldBe` Map.empty Hspec.it "fails when --output is given with check mode" $ do@@ -187,13 +193,13 @@ (".", []) False a `shouldBeFailure` SpecifiedOutputWithCheckMode.SpecifiedOutputWithCheckMode- w `Hspec.shouldBe` []+ w `Hspec.shouldBe` ["warning: --output is deprecated, use piping instead"] s `Hspec.shouldBe` Map.empty Hspec.it "does not overwrite output when input is formatted" $ do let (a, s, w) = runGild- ["--io", "io.cabal"]+ ["io.cabal"] [(Input.File "io.cabal", String.toUtf8 "")] (".", []) False@@ -201,82 +207,82 @@ w `Hspec.shouldBe` [] s `Hspec.shouldBe` Map.empty - Hspec.it "writes to stdout when input is formatted" $ do+ Hspec.it "formats a positional file to output" $ do let (a, s, w) = runGild- ["--input", "p.cabal"]- [(Input.File "p.cabal", String.toUtf8 "")]+ ["io.cabal"]+ [(Input.File "io.cabal", String.toUtf8 "f:a")] (".", []) False a `Hspec.shouldSatisfy` Either.isRight w `Hspec.shouldBe` []- s `Hspec.shouldBe` Map.singleton Output.Stdout (String.toUtf8 "")+ s `Hspec.shouldBe` Map.singleton (Output.File "io.cabal") (String.toUtf8 "f: a\n") - Hspec.it "writes to output when input is formatted" $ do+ Hspec.it "does not overwrite CRLF file when lenient" $ do let (a, s, w) = runGild- ["--input", "p.cabal", "--output", "q.cabal"]- [(Input.File "p.cabal", String.toUtf8 "")]+ ["p.cabal"]+ [(Input.File "p.cabal", String.toUtf8 "s\r\n")] (".", []) False a `Hspec.shouldSatisfy` Either.isRight w `Hspec.shouldBe` []- s `Hspec.shouldBe` Map.singleton (Output.File "q.cabal") (String.toUtf8 "")+ s `Hspec.shouldBe` Map.empty - Hspec.it "writes to output when stdin is formatted" $ do+ Hspec.it "overwrites CRLF file when strict" $ do let (a, s, w) = runGild- ["--output", "q.cabal"]- [(Input.Stdin, String.toUtf8 "")]+ ["--crlf", "strict", "p.cabal"]+ [(Input.File "p.cabal", String.toUtf8 "s\r\n")] (".", []) False a `Hspec.shouldSatisfy` Either.isRight w `Hspec.shouldBe` []- s `Hspec.shouldBe` Map.singleton (Output.File "q.cabal") (String.toUtf8 "")+ s `Hspec.shouldBe` Map.singleton (Output.File "p.cabal") (String.toUtf8 "s\n") - Hspec.it "sets input and output simultaneously" $ do+ Hspec.it "uses --stdin for discovery" $ do let (a, s, w) = runGild- ["--io", "io.cabal"]- [(Input.File "io.cabal", String.toUtf8 "f:a")]- (".", [])+ ["--stdin", "d/p.cabal"]+ [(Input.Stdin, String.toUtf8 "library\n -- cabal-gild: discover\n exposed-modules:")]+ ("d", [["M.hs"]]) False a `Hspec.shouldSatisfy` Either.isRight w `Hspec.shouldBe` []- s `Hspec.shouldBe` Map.singleton (Output.File "io.cabal") (String.toUtf8 "f: a\n")+ s `Hspec.shouldBe` Map.singleton Output.Stdout (String.toUtf8 "library\n -- cabal-gild: discover\n exposed-modules: M\n") - Hspec.it "does not overwrite CRLF file when lenient" $ do- let (a, s, w) =+ Hspec.it "warns when --input is used" $ do+ let (a, _s, w) = runGild- ["--io", "p.cabal"]- [(Input.File "p.cabal", String.toUtf8 "s\r\n")]+ ["--input", "p.cabal"]+ [(Input.File "p.cabal", String.toUtf8 "")] (".", []) False a `Hspec.shouldSatisfy` Either.isRight- w `Hspec.shouldBe` []- s `Hspec.shouldBe` Map.empty+ w `Hspec.shouldBe` ["warning: --input is deprecated, use a positional argument instead"] - Hspec.it "overwrites CRLF file when strict" $ do- let (a, s, w) =+ Hspec.it "warns when --output is used" $ do+ let (a, _s, w) = runGild- ["--crlf", "strict", "--io", "p.cabal"]- [(Input.File "p.cabal", String.toUtf8 "s\r\n")]+ ["--output", "q.cabal"]+ [(Input.Stdin, String.toUtf8 "")] (".", []) False a `Hspec.shouldSatisfy` Either.isRight- w `Hspec.shouldBe` []- s `Hspec.shouldBe` Map.singleton (Output.File "p.cabal") (String.toUtf8 "s\n")+ w `Hspec.shouldBe` ["warning: --output is deprecated, use piping instead"] - Hspec.it "uses --stdin for discovery" $ do- let (a, s, w) =+ Hspec.it "warns when --io is used" $ do+ let (a, _s, w) = runGild- ["--stdin", "d/p.cabal"]- [(Input.Stdin, String.toUtf8 "library\n -- cabal-gild: discover\n exposed-modules:")]- ("d", [["M.hs"]])+ ["--io", "io.cabal"]+ [(Input.File "io.cabal", String.toUtf8 "")]+ (".", []) False a `Hspec.shouldSatisfy` Either.isRight- w `Hspec.shouldBe` []- s `Hspec.shouldBe` Map.singleton Output.Stdout (String.toUtf8 "library\n -- cabal-gild: discover\n exposed-modules: M\n")+ w+ `Hspec.shouldBe` [ "warning: --input is deprecated, use a positional argument instead",+ "warning: --output is deprecated, use piping instead"+ ] Hspec.it "succeeds with empty input" $ do expectGilded@@ -1511,13 +1517,13 @@ let d = "input" (a, s, w) = runGild- ["--input", FilePath.combine d "io.cabal"]+ [FilePath.combine d "io.cabal"] [(Input.File $ FilePath.combine d "io.cabal", String.toUtf8 "library\n -- cabal-gild: discover src --exclude src/N.hs\n exposed-modules:")] (d, [["src", "M.hs"], ["src", "N.hs"]]) False a `Hspec.shouldSatisfy` Either.isRight w `Hspec.shouldBe` []- s `Hspec.shouldBe` Map.singleton Output.Stdout (String.toUtf8 "library\n -- cabal-gild: discover src --exclude src/N.hs\n exposed-modules: M\n")+ s `Hspec.shouldBe` Map.singleton (Output.File $ FilePath.combine d "io.cabal") (String.toUtf8 "library\n -- cabal-gild: discover src --exclude src/N.hs\n exposed-modules: M\n") Hspec.it "allows excluding simple wildcards" $ do expectDiscover@@ -1868,13 +1874,13 @@ let d = "input" (a, s, w) = runGild- ["--input", FilePath.combine d "io.cabal"]+ [FilePath.combine d "io.cabal"] [(Input.File $ FilePath.combine d "io.cabal", String.toUtf8 "library\n -- cabal-gild: discover src --include src/M.hs\n exposed-modules:")] (d, [["src", "M.hs"], ["src", "N.hs"]]) False a `Hspec.shouldSatisfy` Either.isRight w `Hspec.shouldBe` []- s `Hspec.shouldBe` Map.singleton Output.Stdout (String.toUtf8 "library\n -- cabal-gild: discover src --include src/M.hs\n exposed-modules: M\n")+ s `Hspec.shouldBe` Map.singleton (Output.File $ FilePath.combine d "io.cabal") (String.toUtf8 "library\n -- cabal-gild: discover src --include src/M.hs\n exposed-modules: M\n") Hspec.it "discovers asm-sources" $ do expectDiscover@@ -2105,6 +2111,93 @@ w `Hspec.shouldBe` [] s `Hspec.shouldBe` Map.empty + Hspec.it "formats multiple positional files in-place" $ do+ let (a, s, w) =+ runGild+ ["a.cabal", "b.cabal"]+ [ (Input.File "a.cabal", String.toUtf8 "f:a"),+ (Input.File "b.cabal", String.toUtf8 "g:b")+ ]+ (".", [])+ False+ a `Hspec.shouldSatisfy` Either.isRight+ w `Hspec.shouldBe` []+ s+ `Hspec.shouldBe` Map.fromList+ [ (Output.File "a.cabal", String.toUtf8 "f: a\n"),+ (Output.File "b.cabal", String.toUtf8 "g: b\n")+ ]++ Hspec.it "checks multiple positional files" $ do+ let (a, s, w) =+ runGild+ ["--mode", "check", "a.cabal", "b.cabal"]+ [ (Input.File "a.cabal", String.toUtf8 "f: a\n"),+ (Input.File "b.cabal", String.toUtf8 "g: b\n")+ ]+ (".", [])+ False+ a `Hspec.shouldSatisfy` Either.isRight+ w `Hspec.shouldBe` []+ s `Hspec.shouldBe` Map.empty++ Hspec.it "fails check when any positional file is unformatted" $ do+ let (a, s, w) =+ runGild+ ["--mode", "check", "a.cabal", "b.cabal"]+ [ (Input.File "a.cabal", String.toUtf8 "f: a\n"),+ (Input.File "b.cabal", String.toUtf8 "g:b")+ ]+ (".", [])+ False+ a `shouldBeFailure` CheckFailure.CheckFailure+ w `Hspec.shouldBe` []+ s `Hspec.shouldBe` Map.empty++ Hspec.it "fails when positional args are mixed with --input" $ do+ let (a, s, w) =+ runGild+ ["--input", "a.cabal", "b.cabal"]+ []+ (".", [])+ False+ a `shouldBeFailure` MixedArgumentStyles.MixedArgumentStyles "input"+ w `Hspec.shouldBe` []+ s `Hspec.shouldBe` Map.empty++ Hspec.it "fails when positional args are mixed with --output" $ do+ let (a, s, w) =+ runGild+ ["--output", "a.cabal", "b.cabal"]+ []+ (".", [])+ False+ a `shouldBeFailure` MixedArgumentStyles.MixedArgumentStyles "output"+ w `Hspec.shouldBe` []+ s `Hspec.shouldBe` Map.empty++ Hspec.it "fails when positional args are mixed with --io" $ do+ let (a, s, w) =+ runGild+ ["--io", "a.cabal", "b.cabal"]+ []+ (".", [])+ False+ a `shouldBeFailure` MixedArgumentStyles.MixedArgumentStyles "input"+ w `Hspec.shouldBe` []+ s `Hspec.shouldBe` Map.empty++ Hspec.it "fails when positional args are mixed with --stdin" $ do+ let (a, s, w) =+ runGild+ ["--stdin", "a.cabal", "b.cabal"]+ []+ (".", [])+ False+ a `shouldBeFailure` MixedArgumentStyles.MixedArgumentStyles "stdin"+ w `Hspec.shouldBe` []+ s `Hspec.shouldBe` Map.empty+ withTemporaryDirectory :: IO () -> IO () withTemporaryDirectory = Temp.withSystemTempDirectory "cabal-gild"@@ -2222,6 +2315,15 @@ instance (Monad m) => Exception.MonadThrow (TestT m) where throwM = TestT . ExceptT.throwE . Exception.toException++instance (Monad m) => Exception.MonadCatch (TestT m) where+ catch (TestT m) h = TestT . ExceptT.ExceptT $ do+ result <- ExceptT.runExceptT m+ case result of+ Left e -> case Exception.fromException e of+ Just e' -> ExceptT.runExceptT . runTestT $ h e'+ Nothing -> pure (Left e)+ Right a -> pure (Right a) instance (Monad m) => MonadWalk.MonadWalk (TestT m) where walk d i x = do