packages feed

cabal-gild 1.3.1.2 → 1.3.1.3

raw patch · 11 files changed

+364/−42 lines, 11 filesPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

API changes (from Hackage documentation)

+ CabalGild.Unstable.Action.FormatFields: isConditional :: CabalSpecVersion -> Name p -> Bool
+ CabalGild.Unstable.Extra.CharParsing: parens :: CabalParsing m => m a -> m a
+ CabalGild.Unstable.Extra.CharParsing: token :: CabalParsing m => String -> m ()
+ CabalGild.Unstable.Extra.SectionArg: value :: SectionArg a -> ByteString
+ CabalGild.Unstable.Type.Condition: And :: Condition a -> Condition a -> Condition a
+ CabalGild.Unstable.Type.Condition: Lit :: Bool -> Condition a
+ CabalGild.Unstable.Type.Condition: Not :: Condition a -> Condition a
+ CabalGild.Unstable.Type.Condition: Or :: Condition a -> Condition a -> Condition a
+ CabalGild.Unstable.Type.Condition: Par :: Condition a -> Condition a
+ CabalGild.Unstable.Type.Condition: Var :: a -> Condition a
+ CabalGild.Unstable.Type.Condition: data Condition a
+ CabalGild.Unstable.Type.Condition: instance GHC.Classes.Eq a => GHC.Classes.Eq (CabalGild.Unstable.Type.Condition.Condition a)
+ CabalGild.Unstable.Type.Condition: instance GHC.Show.Show a => GHC.Show.Show (CabalGild.Unstable.Type.Condition.Condition a)
+ CabalGild.Unstable.Type.Condition: parseCondition :: ParsecParser a -> ParsecParser (Condition a)
+ CabalGild.Unstable.Type.Condition: parseLit :: CabalParsing m => m Bool
+ CabalGild.Unstable.Type.Condition: prettyCondition :: (a -> Doc) -> Condition a -> Doc
+ CabalGild.Unstable.Type.Variable: Arch :: Arch -> Variable
+ CabalGild.Unstable.Type.Variable: Flag :: FlagName -> Variable
+ CabalGild.Unstable.Type.Variable: Impl :: CompilerFlavor -> VersionRange -> Variable
+ CabalGild.Unstable.Type.Variable: Os :: OS -> Variable
+ CabalGild.Unstable.Type.Variable: data Variable
+ CabalGild.Unstable.Type.Variable: instance GHC.Classes.Eq CabalGild.Unstable.Type.Variable.Variable
+ CabalGild.Unstable.Type.Variable: instance GHC.Show.Show CabalGild.Unstable.Type.Variable.Variable
+ CabalGild.Unstable.Type.Variable: parseArch :: CabalParsing m => m Arch
+ CabalGild.Unstable.Type.Variable: parseFlag :: CabalParsing m => m FlagName
+ CabalGild.Unstable.Type.Variable: parseIdent :: CabalParsing m => m String
+ CabalGild.Unstable.Type.Variable: parseImpl :: CabalParsing m => m (CompilerFlavor, VersionRange)
+ CabalGild.Unstable.Type.Variable: parseOs :: CabalParsing m => m OS
+ CabalGild.Unstable.Type.Variable: parseVariable :: CabalParsing m => m Variable
+ CabalGild.Unstable.Type.Variable: prettyVariable :: Variable -> Doc
- CabalGild.Unstable.Action.Render: field :: Int -> Field (Position, [Comment p]) -> Block
+ CabalGild.Unstable.Action.Render: field :: CabalSpecVersion -> Int -> Field (Position, [Comment p]) -> Block
- CabalGild.Unstable.Action.Render: fields :: Int -> [Field (Position, [Comment p])] -> Block
+ CabalGild.Unstable.Action.Render: fields :: CabalSpecVersion -> Int -> [Field (Position, [Comment p])] -> Block
- CabalGild.Unstable.Action.Render: run :: Applicative m => ([Field (Position, [Comment p])], [Comment p]) -> m ByteString
+ CabalGild.Unstable.Action.Render: run :: Applicative m => CabalSpecVersion -> ([Field (Position, [Comment p])], [Comment p]) -> m ByteString
- CabalGild.Unstable.Action.Render: toByteString :: [Field (Position, [Comment p])] -> [Comment p] -> ByteString
+ CabalGild.Unstable.Action.Render: toByteString :: CabalSpecVersion -> [Field (Position, [Comment p])] -> [Comment p] -> ByteString
- CabalGild.Unstable.Extra.Name: isElif :: Name a -> Bool
+ CabalGild.Unstable.Extra.Name: isElif :: CabalSpecVersion -> Name a -> Bool

Files

README.md view
@@ -1,6 +1,6 @@ # Gild -[![CI](https://github.com/tfausak/cabal-gild/actions/workflows/ci.yaml/badge.svg)](https://github.com/tfausak/cabal-gild/actions/workflows/ci.yaml)+[![CI](https://github.com/tfausak/cabal-gild/actions/workflows/ci.yml/badge.svg)](https://github.com/tfausak/cabal-gild/actions/workflows/ci.yml) [![Hackage](https://badgen.net/hackage/v/cabal-gild)](https://hackage.haskell.org/package/cabal-gild)  Gild is an opinionated command line utility that formats Haskell package@@ -100,7 +100,7 @@  In general you should prefer downloading the appropriate binary for you platform. However it is possible to build Gild from source. It supports Linux,-macOS, and Windows along with the four most recent versions of GHC. Any other+macOS, and Windows along with the three most recent versions of GHC. Any other configurations are unsupported.  With Cabal:
cabal-gild.cabal view
@@ -11,7 +11,7 @@ maintainer: Taylor Fausak name: cabal-gild synopsis: Formats package descriptions.-version: 1.3.1.2+version: 1.3.1.3  source-repository head   type: git@@ -38,7 +38,7 @@     -Wno-safe     -Wno-unsafe -  if impl(ghc >= 9.8)+  if impl(ghc >=9.8)     ghc-options: -Wno-missing-role-annotations    if flag(pedantic)@@ -91,6 +91,7 @@     CabalGild.Unstable.Exception.UnexpectedArgument     CabalGild.Unstable.Exception.UnknownOption     CabalGild.Unstable.Extra.ByteString+    CabalGild.Unstable.Extra.CharParsing     CabalGild.Unstable.Extra.Either     CabalGild.Unstable.Extra.Field     CabalGild.Unstable.Extra.FieldLine@@ -103,6 +104,7 @@     CabalGild.Unstable.Type.Block     CabalGild.Unstable.Type.Chunk     CabalGild.Unstable.Type.Comment+    CabalGild.Unstable.Type.Condition     CabalGild.Unstable.Type.Config     CabalGild.Unstable.Type.Context     CabalGild.Unstable.Type.Dependency@@ -127,6 +129,7 @@     CabalGild.Unstable.Type.Set     CabalGild.Unstable.Type.SomeParsecParser     CabalGild.Unstable.Type.TestedWith+    CabalGild.Unstable.Type.Variable     CabalGild.Unstable.Type.VersionRange    hs-source-dirs: source/library
source/library/CabalGild/Unstable/Action/FormatFields.hs view
@@ -4,7 +4,9 @@  import qualified CabalGild.Unstable.Extra.FieldLine as FieldLine import qualified CabalGild.Unstable.Extra.Name as Name+import qualified CabalGild.Unstable.Extra.SectionArg as SectionArg import qualified CabalGild.Unstable.Extra.String as String+import qualified CabalGild.Unstable.Type.Condition as Condition import qualified CabalGild.Unstable.Type.Dependency as Dependency import qualified CabalGild.Unstable.Type.ExeDependency as ExeDependency import qualified CabalGild.Unstable.Type.Extension as Extension@@ -16,6 +18,8 @@ import qualified CabalGild.Unstable.Type.PkgconfigDependency as PkgconfigDependency import qualified CabalGild.Unstable.Type.SomeParsecParser as SPP import qualified CabalGild.Unstable.Type.TestedWith as TestedWith+import qualified CabalGild.Unstable.Type.Variable as Variable+import qualified Data.ByteString as ByteString import qualified Data.Functor.Identity as Identity import qualified Data.Map as Map import qualified Data.Maybe as Maybe@@ -24,6 +28,7 @@ import qualified Distribution.Fields as Fields import qualified Distribution.ModuleName as ModuleName import qualified Distribution.Parsec as Parsec+import qualified Distribution.Parsec.FieldLineStream as FieldLineStream import qualified Text.PrettyPrint as PrettyPrint  -- | A wrapper around 'field' to allow this to be composed with other actions.@@ -49,7 +54,33 @@             maybe (fst $ Name.annotation n) (fst . FieldLine.annotation) $               Maybe.listToMaybe fls        in Fields.Field n $ fieldLines csv position fls spp-  Fields.Section n sas fs -> Fields.Section n sas $ fmap (field csv) fs+  Fields.Section n sas fs ->+    let result =+          Parsec.runParsecParser' csv (Condition.parseCondition Variable.parseVariable) "<conditional>"+            . FieldLineStream.fieldLineStreamFromBS+            . ByteString.intercalate (ByteString.singleton 0x20)+            $ fmap SectionArg.value sas+        position =+          fst+            . maybe (Name.annotation n) SectionArg.annotation+            $ Maybe.listToMaybe sas+        newSas =+          if isConditional csv n+            then case result of+              Left _ -> sas+              Right c ->+                pure+                  . Fields.SecArgName (position, [])+                  . String.toUtf8+                  . PrettyPrint.renderStyle style+                  $ Condition.prettyCondition Variable.prettyVariable c+            else sas+     in Fields.Section n newSas $ fmap (field csv) fs++isConditional :: CabalSpecVersion.CabalSpecVersion -> Fields.Name p -> Bool+isConditional csv n =+  Name.isIf n+    || Name.isElif csv n  -- | Attempts to parse the given field lines using the given parser. If parsing -- fails, the field lines will be returned as is. Comments within the field
source/library/CabalGild/Unstable/Action/Render.hs view
@@ -9,6 +9,7 @@ import qualified CabalGild.Unstable.Type.Line as Line import qualified Data.ByteString as ByteString import qualified Data.Function as Function+import qualified Distribution.CabalSpecVersion as CabalSpecVersion import qualified Distribution.Compat.Lens as Lens import qualified Distribution.Fields as Fields import qualified Distribution.Parsec.Position as Position@@ -17,32 +18,34 @@ -- actions. run ::   (Applicative m) =>+  CabalSpecVersion.CabalSpecVersion ->   ([Fields.Field (Position.Position, [Comment.Comment p])], [Comment.Comment p]) ->   m ByteString.ByteString-run = pure . uncurry toByteString+run csv = pure . uncurry (toByteString csv)  -- | Renders the given fields and comments to a byte string. toByteString ::+  CabalSpecVersion.CabalSpecVersion ->   [Fields.Field (Position.Position, [Comment.Comment p])] ->   [Comment.Comment p] ->   ByteString.ByteString-toByteString fs cs =+toByteString csv fs cs =   let i = 0 :: Int    in Block.toByteString         . Lens.set Block.lineBeforeLens False         . Lens.set Block.lineAfterLens True-        $ fields i fs <> comments i cs+        $ fields csv i fs <> comments i cs  -- | Renders the given fields to a block at the given indentation level.-fields :: Int -> [Fields.Field (Position.Position, [Comment.Comment p])] -> Block.Block-fields = foldMap . field+fields :: CabalSpecVersion.CabalSpecVersion -> Int -> [Fields.Field (Position.Position, [Comment.Comment p])] -> Block.Block+fields csv = foldMap . field csv  -- | Renders the given field to a block at the given indentation level. -- -- If a field only has one line and no comments, then it can be rendered all on -- one line.-field :: Int -> Fields.Field (Position.Position, [Comment.Comment p]) -> Block.Block-field i f = case f of+field :: CabalSpecVersion.CabalSpecVersion -> Int -> Fields.Field (Position.Position, [Comment.Comment p]) -> Block.Block+field csv i f = case f of   Fields.Field n fls -> case fls of     [fl]       | null . snd $ FieldLine.annotation fl,@@ -62,8 +65,8 @@               }           <> fieldLines (i + 1) fls   Fields.Section n sas fs ->-    Lens.set Block.lineBeforeLens (not $ Name.isElif n || Name.isElse n)-      . Lens.set Block.lineAfterLens (not $ Name.isIf n || Name.isElif n)+    Lens.set Block.lineBeforeLens (not $ Name.isElif csv n || Name.isElse n)+      . Lens.set Block.lineAfterLens (not $ Name.isIf n || Name.isElif csv n)       $ comments i (snd $ Name.annotation n)         <> comments i (concatMap (snd . SectionArg.annotation) sas)         <> Block.fromLine@@ -71,7 +74,7 @@             { Line.indent = i,               Line.chunk = Lens.set Chunk.spaceAfterLens True (name n) <> sectionArgs sas             }-        <> Lens.set Block.lineBeforeLens False (fields (i + 1) fs)+        <> Lens.set Block.lineBeforeLens False (fields csv (i + 1) fs)  -- | Returns true if the two positions are on the same row. sameRow :: (Position.Position, cs) -> (Position.Position, cs) -> Bool@@ -108,25 +111,13 @@  -- | Renders the given section argument to a chunk. sectionArg :: Fields.SectionArg a -> Chunk.Chunk-sectionArg sa = case sa of-  Fields.SecArgName _ bs ->-    Lens.set Chunk.spaceBeforeLens True-      . Lens.set Chunk.spaceAfterLens True-      $ Chunk.fromByteString bs-  Fields.SecArgStr _ bs ->-    Lens.set Chunk.spaceBeforeLens True-      . Lens.set Chunk.spaceAfterLens True-      . Chunk.fromByteString-      . flip ByteString.snoc 0x22-      $ ByteString.cons 0x22 bs-  Fields.SecArgOther _ bs ->-    let b =-          bs /= ByteString.singleton 0x21 -- !-            && bs /= ByteString.singleton 0x28 -- (-            && bs /= ByteString.singleton 0x29 -- )-     in Lens.set Chunk.spaceBeforeLens b-          . Lens.set Chunk.spaceAfterLens b-          $ Chunk.fromByteString bs+sectionArg sa = Lens.set Chunk.spaceBeforeLens True+  . Lens.set Chunk.spaceAfterLens True+  . Chunk.fromByteString+  $ case sa of+    Fields.SecArgName _ bs -> bs+    Fields.SecArgStr _ bs -> flip ByteString.snoc 0x22 $ ByteString.cons 0x22 bs+    Fields.SecArgOther _ bs -> bs  -- | Renders the given comments to a block at the given indentation level. comments :: Int -> [Comment.Comment a] -> Block.Block
+ source/library/CabalGild/Unstable/Extra/CharParsing.hs view
@@ -0,0 +1,10 @@+module CabalGild.Unstable.Extra.CharParsing where++import qualified Distribution.Compat.CharParsing as Parse+import qualified Distribution.Parsec as Parsec++parens :: (Parsec.CabalParsing m) => m a -> m a+parens = Parse.between (token "(") (token ")")++token :: (Parsec.CabalParsing m) => String -> m ()+token s = Parse.string s *> Parse.spaces
source/library/CabalGild/Unstable/Extra/Name.hs view
@@ -1,6 +1,7 @@ module CabalGild.Unstable.Extra.Name where  import qualified CabalGild.Unstable.Extra.String as String+import qualified Distribution.CabalSpecVersion as CabalSpecVersion import qualified Distribution.Compat.Lens as Lens import qualified Distribution.Fields as Fields @@ -21,8 +22,10 @@ isIf = (== String.toUtf8 "if") . value  -- | Returns true when the name is @"elif"@, false otherwise.-isElif :: Fields.Name a -> Bool-isElif = (== String.toUtf8 "elif") . value+isElif :: CabalSpecVersion.CabalSpecVersion -> Fields.Name a -> Bool+isElif csv n =+  csv >= CabalSpecVersion.CabalSpecV2_2+    && value n == String.toUtf8 "elif"  -- | Returns true when the name is @"else"@, false otherwise. isElse :: Fields.Name a -> Bool
source/library/CabalGild/Unstable/Extra/SectionArg.hs view
@@ -1,5 +1,6 @@ module CabalGild.Unstable.Extra.SectionArg where +import qualified Data.ByteString as ByteString import qualified Distribution.Fields as Fields  -- | Extracts the annotation from the given 'Fields.SectionArg'.@@ -8,3 +9,10 @@   Fields.SecArgName x _ -> x   Fields.SecArgStr x _ -> x   Fields.SecArgOther x _ -> x++-- | Extracts the value from the given 'Fields.SectionArg'.+value :: Fields.SectionArg a -> ByteString.ByteString+value sa = case sa of+  Fields.SecArgName _ x -> x+  Fields.SecArgStr _ x -> x+  Fields.SecArgOther _ x -> x
source/library/CabalGild/Unstable/Main.hs view
@@ -97,7 +97,7 @@       Monad.>=> ReflowText.run csv       Monad.>=> EvaluatePragmas.run filePath       Monad.>=> FormatFields.run csv-      Monad.>=> Render.run+      Monad.>=> Render.run csv     )     (fields, comments) 
+ source/library/CabalGild/Unstable/Type/Condition.hs view
@@ -0,0 +1,68 @@+{-# LANGUAGE FlexibleContexts #-}++module CabalGild.Unstable.Type.Condition where++import qualified CabalGild.Unstable.Extra.CharParsing as Parse+import qualified Distribution.Compat.CharParsing as Parse+import qualified Distribution.Parsec as Parsec+import qualified Text.Parsec as P+import qualified Text.Parsec.Expr as PE+import qualified Text.PrettyPrint as PrettyPrint++data Condition a+  = Par (Condition a)+  | Not (Condition a)+  | And (Condition a) (Condition a)+  | Or (Condition a) (Condition a)+  | Lit Bool+  | Var a+  deriving (Eq, Show)++parseCondition :: Parsec.ParsecParser a -> Parsec.ParsecParser (Condition a)+parseCondition parseVariable = Parsec.PP $ \csv -> do+  let operators :: (P.Stream s m Char) => PE.OperatorTable s u m (Condition b)+      operators =+        [ [PE.Prefix (Not <$ Parse.char '!' <* Parse.spaces)],+          [PE.Infix (And <$ Parse.string "&&" <* Parse.spaces) PE.AssocRight],+          [PE.Infix (Or <$ Parse.string "||" <* Parse.spaces) PE.AssocRight]+        ]+  Parse.spaces+  PE.buildExpressionParser operators $+    Parsec.unPP+      ( Parse.choice+          [ Par <$> Parse.parens (parseCondition parseVariable),+            Not <$> (Parse.token "!" *> parseCondition parseVariable),+            Lit <$> Parse.try parseLit,+            Var <$> parseVariable+          ]+      )+      csv++parseLit :: (Parsec.CabalParsing m) => m Bool+parseLit =+  Parse.choice+    [ True <$ Parse.token "True",+      True <$ Parse.token "true",+      False <$ Parse.token "False",+      False <$ Parse.token "false"+    ]++prettyCondition :: (a -> PrettyPrint.Doc) -> Condition a -> PrettyPrint.Doc+prettyCondition f x =+  case x of+    Par y -> PrettyPrint.parens (prettyCondition f y)+    Not y -> PrettyPrint.char '!' <> prettyCondition f y+    And y z ->+      PrettyPrint.hsep+        [ prettyCondition f y,+          PrettyPrint.text "&&",+          prettyCondition f z+        ]+    Or y z ->+      PrettyPrint.hsep+        [ prettyCondition f y,+          PrettyPrint.text "||",+          prettyCondition f z+        ]+    Lit y -> PrettyPrint.text $ if y then "true" else "false"+    Var y -> f y
+ source/library/CabalGild/Unstable/Type/Variable.hs view
@@ -0,0 +1,72 @@+module CabalGild.Unstable.Type.Variable where++import qualified CabalGild.Unstable.Extra.CharParsing as Parse+import qualified Data.Char as Char+import qualified Distribution.Compat.CharParsing as Parse+import qualified Distribution.Compiler as Compiler+import qualified Distribution.Parsec as Parsec+import qualified Distribution.Pretty as Pretty+import qualified Distribution.System as System+import qualified Distribution.Types.Flag as Flag+import qualified Distribution.Types.VersionRange as VersionRange+import qualified Text.PrettyPrint as PrettyPrint++data Variable+  = Arch System.Arch+  | Flag Flag.FlagName+  | Impl Compiler.CompilerFlavor VersionRange.VersionRange+  | Os System.OS+  deriving (Eq, Show)++parseVariable :: (Parsec.CabalParsing m) => m Variable+parseVariable =+  Parse.choice+    [ Arch <$> parseArch,+      Flag <$> parseFlag,+      uncurry Impl <$> parseImpl,+      Os <$> parseOs+    ]++parseArch :: (Parsec.CabalParsing m) => m System.Arch+parseArch =+  fmap (System.classifyArch System.Permissive) $+    Parse.token "arch" *> Parse.parens parseIdent++parseFlag :: (Parsec.CabalParsing m) => m Flag.FlagName+parseFlag = Parse.token "flag" *> Parse.parens (Parsec.parsec <* Parse.spaces)++parseImpl :: (Parsec.CabalParsing m) => m (Compiler.CompilerFlavor, VersionRange.VersionRange)+parseImpl = do+  Parse.token "impl"+  Parse.parens $+    (,)+      <$> Parsec.parsec+      <* Parse.spaces+      <*> Parse.option VersionRange.anyVersion Parsec.parsec+      <* Parse.spaces++parseOs :: (Parsec.CabalParsing m) => m System.OS+parseOs =+  fmap (System.classifyOS System.Permissive) $+    Parse.token "os" *> Parse.parens parseIdent++parseIdent :: (Parsec.CabalParsing m) => m String+parseIdent =+  let isIdent c = Char.isAlphaNum c || c == '_' || c == '-'+   in Parse.munch1 isIdent <* Parse.spaces++prettyVariable :: Variable -> PrettyPrint.Doc+prettyVariable x =+  case x of+    Arch y ->+      PrettyPrint.text "arch"+        <> PrettyPrint.parens (Pretty.pretty y)+    Flag y ->+      PrettyPrint.text "flag"+        <> PrettyPrint.parens (Pretty.pretty y)+    Impl y z ->+      PrettyPrint.text "impl"+        <> PrettyPrint.parens (Pretty.pretty y PrettyPrint.<+> Pretty.pretty z)+    Os y ->+      PrettyPrint.text "os"+        <> PrettyPrint.parens (Pretty.pretty y)
source/test-suite/Main.hs view
@@ -521,8 +521,139 @@   Hspec.it "properly formats conditionals" $ do     expectGilded       "if ! impl ( ghc >= 9.8 )"-      "if !impl(ghc >= 9.8)\n"+      "if !impl(ghc >=9.8)\n" +  Hspec.describe "conditionals" $ do+    Hspec.it "formats variable" $ do+      expectGilded+        "if flag ( x )"+        "if flag(x)\n"++    Hspec.it "formats false" $ do+      expectGilded+        "if false"+        "if false\n"++    Hspec.it "formats upper false" $ do+      expectGilded+        "if False"+        "if false\n"++    Hspec.it "formats true" $ do+      expectGilded+        "if true"+        "if true\n"++    Hspec.it "formats upper true" $ do+      expectGilded+        "if True"+        "if true\n"++    Hspec.it "formats not" $ do+      expectGilded+        "if ! flag ( x )"+        "if !flag(x)\n"++    Hspec.it "formats or" $ do+      expectGilded+        "if flag ( x )||flag ( y )"+        "if flag(x) || flag(y)\n"++    Hspec.it "formats and" $ do+      expectGilded+        "if flag ( x )&&flag ( y )"+        "if flag(x) && flag(y)\n"++    Hspec.it "formats arch" $ do+      expectGilded+        "if arch ( aarch64 )"+        "if arch(aarch64)\n"++    Hspec.it "formats upper arch" $ do+      expectGilded+        "if arch ( AARCH64 )"+        "if arch(aarch64)\n"++    Hspec.it "formats arch alias" $ do+      expectGilded+        "if arch ( arm64 )"+        "if arch(aarch64)\n"++    Hspec.it "formats flag" $ do+      expectGilded+        "if flag ( x )"+        "if flag(x)\n"++    Hspec.it "formats upper flag" $ do+      expectGilded+        "if flag ( X )"+        "if flag(x)\n"++    Hspec.it "formats impl" $ do+      expectGilded+        "if impl ( ghc > 0 )"+        "if impl(ghc >0)\n"++    Hspec.it "formats upper impl" $ do+      expectGilded+        "if impl ( GHC > 0 )"+        "if impl(ghc >0)\n"++    Hspec.it "formats impl without version range" $ do+      expectGilded+        "if impl ( ghc )"+        "if impl(ghc >=0)\n"++    Hspec.it "formats os" $ do+      expectGilded+        "if os ( osx )"+        "if os(osx)\n"++    Hspec.it "formats upper os" $ do+      expectGilded+        "if os ( OSX )"+        "if os(osx)\n"++    Hspec.it "formats os alias" $ do+      expectGilded+        "if os ( darwin )"+        "if os(osx)\n"++    Hspec.it "does not format old elif" $ do+      expectGilded+        "elif flag ( x )"+        "elif flag ( x )\n"++    Hspec.it "formats new elif" $ do+      expectGilded+        "cabal-version: 2.2\nelif flag ( x )"+        "cabal-version: 2.2\nelif flag(x)\n"++    Hspec.it "keeps explicit parentheses" $ do+      expectGilded+        "if ( true )"+        "if (true)\n"++    Hspec.it "formats multiple nots" $ do+      expectGilded+        "if ! ! flag ( a )"+        "if !!flag(a)\n"++    Hspec.it "formats multiple ands" $ do+      expectGilded+        "if flag ( a ) && flag ( b ) && flag ( c )"+        "if flag(a) && flag(b) && flag(c)\n"++    Hspec.it "formats multiple ors" $ do+      expectGilded+        "if flag ( a ) || flag ( b ) || flag ( c )"+        "if flag(a) || flag(b) || flag(c)\n"++    Hspec.it "formats mixed operators" $ do+      expectGilded+        "if ! flag ( a ) && flag ( b ) || flag ( c )"+        "if !flag(a) && flag(b) || flag(c)\n"+   Hspec.describe "license-files" $ do     -- These tests apply to other "list" fields as well. The license-files     -- field is just a representative example.@@ -1203,15 +1334,20 @@       "if p\n a\nelse\n b"       "if p\n  a\nelse\n  b\n" -  Hspec.it "groups 'elif' with 'if'" $ do+  Hspec.it "does not group old 'elif' with 'if'" $ do     expectGilded       "if p\n a\nelif q\n b"-      "if p\n  a\nelif q\n  b\n"+      "if p\n  a\n\nelif q\n  b\n" +  Hspec.it "groups new 'elif' with 'if'" $ do+    expectGilded+      "cabal-version: 2.2\nif p\n a\nelif q\n b"+      "cabal-version: 2.2\n\nif p\n  a\nelif q\n  b\n"+   Hspec.it "groups 'else' with 'elif'" $ do     expectGilded-      "if p\n a\nelif q\n b\nelse\n c"-      "if p\n  a\nelif q\n  b\nelse\n  c\n"+      "cabal-version: 2.2\nif p\n a\nelif q\n b\nelse\n c"+      "cabal-version: 2.2\n\nif p\n  a\nelif q\n  b\nelse\n  c\n"    Hspec.it "does not group 'else' with anything else" $ do     expectGilded