module Distribution.PackageDescription.PrettyPrint (
writeGenericPackageDescription,
showGenericPackageDescription,
) where
import Distribution.PackageDescription
( TestSuite(..), TestSuiteInterface(..), testType
, SourceRepo(..),
customFieldsBI, CondTree(..), Condition(..),
FlagName(..), ConfVar(..), Executable(..), Library(..),
Flag(..), PackageDescription(..),
GenericPackageDescription(..))
import Text.PrettyPrint
(hsep, comma, punctuate, fsep, parens, char, nest, empty,
isEmpty, ($$), (<+>), colon, (<>), text, vcat, ($+$), Doc, render)
import Distribution.Simple.Utils (writeUTF8File)
import Distribution.ParseUtils (showFreeText, FieldDescr(..))
import Distribution.PackageDescription.Parse (pkgDescrFieldDescrs,binfoFieldDescrs,libFieldDescrs,
sourceRepoFieldDescrs)
import Distribution.Package (Dependency(..))
import Distribution.Text (Text(..))
import Data.Maybe (isJust, fromJust, isNothing)
indentWith :: Int
indentWith = 4
simplifiedPrinting :: Bool
simplifiedPrinting = False :: BoolFalse
writeGenericPackageDescription :: FilePath -> GenericPackageDescription -> IO ()
writeGenericPackageDescription fpath pkg = writeUTF8File :: FilePath -> String -> IO ()writeUTF8File fpath :: FilePathfpath (showGenericPackageDescription ::
GenericPackageDescription -> StringshowGenericPackageDescription pkg :: GenericPackageDescriptionpkg)
showGenericPackageDescription :: GenericPackageDescription -> String
showGenericPackageDescription = render :: Doc -> Stringrender (.) :: (b -> c) -> (a -> b) -> a -> c. ppGenericPackageDescription :: GenericPackageDescription -> DocppGenericPackageDescription
ppGenericPackageDescription :: GenericPackageDescription -> Doc
ppGenericPackageDescription gpd =
ppPackageDescription :: PackageDescription -> DocppPackageDescription (packageDescription ::
GenericPackageDescription -> PackageDescriptionpackageDescription gpd :: GenericPackageDescriptiongpd)
($+$) :: Doc -> Doc -> Doc$+$ ppGenPackageFlags :: [Flag] -> DocppGenPackageFlags (genPackageFlags :: GenericPackageDescription -> [Flag]genPackageFlags gpd :: GenericPackageDescriptiongpd)
($+$) :: Doc -> Doc -> Doc$+$ ppLibrary :: Maybe (CondTree ConfVar [Dependency] Library) -> DocppLibrary (condLibrary ::
GenericPackageDescription
-> Maybe (CondTree ConfVar [Dependency] Library)condLibrary gpd :: GenericPackageDescriptiongpd)
($+$) :: Doc -> Doc -> Doc$+$ ppExecutables ::
[(String, CondTree ConfVar [Dependency] Executable)] -> DocppExecutables (condExecutables ::
GenericPackageDescription
-> [(String, CondTree ConfVar [Dependency] Executable)]condExecutables gpd :: GenericPackageDescriptiongpd)
($+$) :: Doc -> Doc -> Doc$+$ ppTestSuites ::
[(String, CondTree ConfVar [Dependency] TestSuite)] -> DocppTestSuites (condTestSuites ::
GenericPackageDescription
-> [(String, CondTree ConfVar [Dependency] TestSuite)]condTestSuites gpd :: GenericPackageDescriptiongpd)
ppPackageDescription :: PackageDescription -> Doc
ppPackageDescription pd = ppFields :: [FieldDescr a] -> a -> DocppFields pkgDescrFieldDescrs :: [FieldDescr PackageDescription]pkgDescrFieldDescrs pd :: PackageDescriptionpd
($+$) :: Doc -> Doc -> Doc$+$ ppCustomFields :: [(String, String)] -> DocppCustomFields (customFieldsPD :: PackageDescription -> [(String, String)]customFieldsPD pd :: PackageDescriptionpd)
($+$) :: Doc -> Doc -> Doc$+$ ppSourceRepos :: [SourceRepo] -> DocppSourceRepos (sourceRepos :: PackageDescription -> [SourceRepo]sourceRepos pd :: PackageDescriptionpd)
ppSourceRepos :: [SourceRepo] -> Doc
ppSourceRepos [] = empty :: Docempty
ppSourceRepos (hd:tl) = ppSourceRepo :: SourceRepo -> DocppSourceRepo hd :: SourceRepohd ($+$) :: Doc -> Doc -> Doc$+$ ppSourceRepos :: [SourceRepo] -> DocppSourceRepos tl :: [SourceRepo]tl
ppSourceRepo :: SourceRepo -> Doc
ppSourceRepo repo =
emptyLine :: Doc -> DocemptyLine ($) :: (a -> b) -> a -> b$ text :: String -> Doctext "source-repository" (<+>) :: Doc -> Doc -> Doc<+> disp :: Text a => a -> Docdisp (repoKind :: SourceRepo -> RepoKindrepoKind repo :: SourceReporepo) ($+$) :: Doc -> Doc -> Doc$+$
(nest :: Int -> Doc -> Docnest indentWith :: IntindentWith (ppFields :: [FieldDescr a] -> a -> DocppFields sourceRepoFieldDescrs' :: [FieldDescr SourceRepo]sourceRepoFieldDescrs' repo :: SourceReporepo))
where
sourceRepoFieldDescrs' = [fd :: FieldDescr SourceRepofd | fd <- sourceRepoFieldDescrs :: [FieldDescr SourceRepo]sourceRepoFieldDescrs, fieldName :: FieldDescr a -> StringfieldName fd :: FieldDescr SourceRepofd (/=) :: Eq a => a -> a -> Bool/= "kind"]
ppFields :: [FieldDescr a] -> a -> Doc
ppFields fields x =
vcat :: [Doc] -> Docvcat [ ppField :: String -> Doc -> DocppField name :: FlagNamename (getter :: a -> Docgetter x :: ax)
| FieldDescr name getter _ <- fields :: [FieldDescr a]fields]
ppField :: String -> Doc -> Doc
ppField name fielddoc | isEmpty :: Doc -> BoolisEmpty fielddoc :: Docfielddoc = empty :: Docempty
| otherwise :: Boolotherwise = text :: String -> Doctext name :: FlagNamename (<>) :: Doc -> Doc -> Doc<> colon :: Doccolon (<+>) :: Doc -> Doc -> Doc<+> fielddoc :: Docfielddoc
ppDiffFields :: [FieldDescr a] -> a -> a -> Doc
ppDiffFields fields x y =
vcat :: [Doc] -> Docvcat [ ppField :: String -> Doc -> DocppField name :: FlagNamename (getter :: a -> Docgetter x :: ax)
| FieldDescr name getter _ <- fields :: [FieldDescr a]fields,
render :: Doc -> Stringrender (getter :: a -> Docgetter x :: ax) (/=) :: Eq a => a -> a -> Bool/= render :: Doc -> Stringrender (getter :: a -> Docgetter y :: ay)]
ppCustomFields :: [(String,String)] -> Doc
ppCustomFields flds = vcat :: [Doc] -> Docvcat [ppCustomField :: (String, String) -> DocppCustomField f :: Stringf | f <- flds :: [Flag]flds]
ppCustomField :: (String,String) -> Doc
ppCustomField (name,val) = text :: String -> Doctext name :: FlagNamename (<>) :: Doc -> Doc -> Doc<> colon :: Doccolon (<+>) :: Doc -> Doc -> Doc<+> showFreeText :: String -> DocshowFreeText val :: Stringval
ppGenPackageFlags :: [Flag] -> Doc
ppGenPackageFlags flds = vcat :: [Doc] -> Docvcat [ppFlag :: Flag -> DocppFlag f :: Stringf | f <- flds :: [Flag]flds]
ppFlag :: Flag -> Doc
ppFlag (MkFlag name desc dflt manual) =
emptyLine :: Doc -> DocemptyLine ($) :: (a -> b) -> a -> b$ text :: String -> Doctext "flag" (<+>) :: Doc -> Doc -> Doc<+> ppFlagName :: FlagName -> DocppFlagName name :: FlagNamename ($+$) :: Doc -> Doc -> Doc$+$
(nest :: Int -> Doc -> Docnest indentWith :: IntindentWith ((if null :: [a] -> Boolnull desc :: Stringdesc
then empty :: Docempty
else text :: String -> Doctext "Description: " (<+>) :: Doc -> Doc -> Doc<+> showFreeText :: String -> DocshowFreeText desc :: Stringdesc) ($+$) :: Doc -> Doc -> Doc$+$
(if dflt :: Booldflt then empty :: Docempty else text :: String -> Doctext "Default: False") ($+$) :: Doc -> Doc -> Doc$+$
(if manual :: Boolmanual then text :: String -> Doctext "Manual: True" else empty :: Docempty)))
ppLibrary :: (Maybe (CondTree ConfVar [Dependency] Library)) -> Doc
ppLibrary Nothing = empty :: Docempty
ppLibrary (Just condTree) =
emptyLine :: Doc -> DocemptyLine ($) :: (a -> b) -> a -> b$ text :: String -> Doctext "library" ($+$) :: Doc -> Doc -> Doc$+$ nest :: Int -> Doc -> Docnest indentWith :: IntindentWith (ppCondTree ::
CondTree ConfVar [Dependency] a
-> Maybe a
-> (a -> Maybe a -> Doc)
-> DocppCondTree condTree :: CondTree ConfVar [Dependency] TestSuitecondTree Nothing :: Maybe aNothing ppLib :: Library -> Maybe Library -> DocppLib)
where
ppLib lib Nothing = ppFields :: [FieldDescr a] -> a -> DocppFields libFieldDescrs :: [FieldDescr Library]libFieldDescrs lib :: Librarylib
($$) :: Doc -> Doc -> Doc$$ ppCustomFields :: [(String, String)] -> DocppCustomFields (customFieldsBI :: BuildInfo -> [(String, String)]customFieldsBI (libBuildInfo :: Library -> BuildInfolibBuildInfo lib :: Librarylib))
ppLib lib (Just plib) = ppDiffFields :: [FieldDescr a] -> a -> a -> DocppDiffFields libFieldDescrs :: [FieldDescr Library]libFieldDescrs lib :: Librarylib plib :: Libraryplib
($$) :: Doc -> Doc -> Doc$$ ppCustomFields :: [(String, String)] -> DocppCustomFields (customFieldsBI :: BuildInfo -> [(String, String)]customFieldsBI (libBuildInfo :: Library -> BuildInfolibBuildInfo lib :: Librarylib))
ppExecutables :: [(String, CondTree ConfVar [Dependency] Executable)] -> Doc
ppExecutables exes =
vcat :: [Doc] -> Docvcat [emptyLine :: Doc -> DocemptyLine ($) :: (a -> b) -> a -> b$ text :: String -> Doctext ("executable " (++) :: [a] -> [a] -> [a]++ n :: Stringn)
($+$) :: Doc -> Doc -> Doc$+$ nest :: Int -> Doc -> Docnest indentWith :: IntindentWith (ppCondTree ::
CondTree ConfVar [Dependency] a
-> Maybe a
-> (a -> Maybe a -> Doc)
-> DocppCondTree condTree :: CondTree ConfVar [Dependency] TestSuitecondTree Nothing :: Maybe aNothing ppExe :: Executable -> Maybe Executable -> DocppExe)| (n,condTree) <- exes :: [(String, CondTree ConfVar [Dependency] Executable)]exes]
where
ppExe (Executable _ modulePath' buildInfo') Nothing =
(if modulePath' :: FilePathmodulePath' (==) :: Eq a => a -> a -> Bool== "" then empty :: Docempty else text :: String -> Doctext "main-is:" (<+>) :: Doc -> Doc -> Doc<+> text :: String -> Doctext modulePath' :: FilePathmodulePath')
($+$) :: Doc -> Doc -> Doc$+$ ppFields :: [FieldDescr a] -> a -> DocppFields binfoFieldDescrs :: [FieldDescr BuildInfo]binfoFieldDescrs buildInfo' :: BuildInfobuildInfo'
($+$) :: Doc -> Doc -> Doc$+$ ppCustomFields :: [(String, String)] -> DocppCustomFields (customFieldsBI :: BuildInfo -> [(String, String)]customFieldsBI buildInfo' :: BuildInfobuildInfo')
ppExe (Executable _ modulePath' buildInfo')
(Just (Executable _ modulePath2 buildInfo2)) =
(if modulePath' :: FilePathmodulePath' (==) :: Eq a => a -> a -> Bool== "" (||) :: Bool -> Bool -> Bool|| modulePath' :: FilePathmodulePath' (==) :: Eq a => a -> a -> Bool== modulePath2 :: FilePathmodulePath2
then empty :: Docempty else text :: String -> Doctext "main-is:" (<+>) :: Doc -> Doc -> Doc<+> text :: String -> Doctext modulePath' :: FilePathmodulePath')
($+$) :: Doc -> Doc -> Doc$+$ ppDiffFields :: [FieldDescr a] -> a -> a -> DocppDiffFields binfoFieldDescrs :: [FieldDescr BuildInfo]binfoFieldDescrs buildInfo' :: BuildInfobuildInfo' buildInfo2 :: BuildInfobuildInfo2
($+$) :: Doc -> Doc -> Doc$+$ ppCustomFields :: [(String, String)] -> DocppCustomFields (customFieldsBI :: BuildInfo -> [(String, String)]customFieldsBI buildInfo' :: BuildInfobuildInfo')
ppTestSuites :: [(String, CondTree ConfVar [Dependency] TestSuite)] -> Doc
ppTestSuites suites =
emptyLine :: Doc -> DocemptyLine ($) :: (a -> b) -> a -> b$ vcat :: [Doc] -> Docvcat [ text :: String -> Doctext ("test-suite " (++) :: [a] -> [a] -> [a]++ n :: Stringn)
($+$) :: Doc -> Doc -> Doc$+$ nest :: Int -> Doc -> Docnest indentWith :: IntindentWith (ppCondTree ::
CondTree ConfVar [Dependency] a
-> Maybe a
-> (a -> Maybe a -> Doc)
-> DocppCondTree condTree :: CondTree ConfVar [Dependency] TestSuitecondTree Nothing :: Maybe aNothing ppTestSuite :: TestSuite -> Maybe TestSuite -> DocppTestSuite)
| (n,condTree) <- suites :: [(String, CondTree ConfVar [Dependency] TestSuite)]suites]
where
ppTestSuite testsuite Nothing =
text :: String -> Doctext "type:" (<+>) :: Doc -> Doc -> Doc<+> disp :: Text a => a -> Docdisp (testType :: TestSuite -> TestTypetestType testsuite :: TestSuitetestsuite)
($+$) :: Doc -> Doc -> Doc$+$ maybe :: b -> (a -> b) -> Maybe a -> bmaybe empty :: Docempty (\f -> text :: String -> Doctext "main-is:" (<+>) :: Doc -> Doc -> Doc<+> text :: String -> Doctext f :: Stringf)
(testSuiteMainIs :: TestSuite -> Maybe FilePathtestSuiteMainIs testsuite :: TestSuitetestsuite)
($+$) :: Doc -> Doc -> Doc$+$ maybe :: b -> (a -> b) -> Maybe a -> bmaybe empty :: Docempty (\m -> text :: String -> Doctext "test-module:" (<+>) :: Doc -> Doc -> Doc<+> disp :: Text a => a -> Docdisp m :: ModuleNamem)
(testSuiteModule :: TestSuite -> Maybe ModuleNametestSuiteModule testsuite :: TestSuitetestsuite)
($+$) :: Doc -> Doc -> Doc$+$ ppFields :: [FieldDescr a] -> a -> DocppFields binfoFieldDescrs :: [FieldDescr BuildInfo]binfoFieldDescrs (testBuildInfo :: TestSuite -> BuildInfotestBuildInfo testsuite :: TestSuitetestsuite)
($+$) :: Doc -> Doc -> Doc$+$ ppCustomFields :: [(String, String)] -> DocppCustomFields (customFieldsBI :: BuildInfo -> [(String, String)]customFieldsBI (testBuildInfo :: TestSuite -> BuildInfotestBuildInfo testsuite :: TestSuitetestsuite))
ppTestSuite (TestSuite _ _ buildInfo' _)
(Just (TestSuite _ _ buildInfo2 _)) =
ppDiffFields :: [FieldDescr a] -> a -> a -> DocppDiffFields binfoFieldDescrs :: [FieldDescr BuildInfo]binfoFieldDescrs buildInfo' :: BuildInfobuildInfo' buildInfo2 :: BuildInfobuildInfo2
($+$) :: Doc -> Doc -> Doc$+$ ppCustomFields :: [(String, String)] -> DocppCustomFields (customFieldsBI :: BuildInfo -> [(String, String)]customFieldsBI buildInfo' :: BuildInfobuildInfo')
testSuiteMainIs test = case testInterface :: TestSuite -> TestSuiteInterfacetestInterface test :: TestSuitetest of
TestSuiteExeV10 _ f -> Just :: a -> Maybe aJust f :: Stringf
_ -> Nothing :: Maybe aNothing
testSuiteModule test = case testInterface :: TestSuite -> TestSuiteInterfacetestInterface test :: TestSuitetest of
TestSuiteLibV09 _ m -> Just :: a -> Maybe aJust m :: ModuleNamem
_ -> Nothing :: Maybe aNothing
ppCondition :: Condition ConfVar -> Doc
ppCondition (Var x) = ppConfVar :: ConfVar -> DocppConfVar x :: ax
ppCondition (Lit b) = text :: String -> Doctext (show :: Show a => a -> Stringshow b :: Boolb)
ppCondition (CNot c) = char :: Char -> Docchar '!' (<>) :: Doc -> Doc -> Doc<> (ppCondition :: Condition ConfVar -> DocppCondition c :: Condition ConfVarc)
ppCondition (COr c1 c2) = parens :: Doc -> Docparens (hsep :: [Doc] -> Dochsep [ppCondition :: Condition ConfVar -> DocppCondition c1 :: Condition ConfVarc1, text :: String -> Doctext "||"
(<+>) :: Doc -> Doc -> Doc<+> ppCondition :: Condition ConfVar -> DocppCondition c2 :: Condition ConfVarc2])
ppCondition (CAnd c1 c2) = parens :: Doc -> Docparens (hsep :: [Doc] -> Dochsep [ppCondition :: Condition ConfVar -> DocppCondition c1 :: Condition ConfVarc1, text :: String -> Doctext "&&"
(<+>) :: Doc -> Doc -> Doc<+> ppCondition :: Condition ConfVar -> DocppCondition c2 :: Condition ConfVarc2])
ppConfVar :: ConfVar -> Doc
ppConfVar (OS os) = text :: String -> Doctext "os" (<>) :: Doc -> Doc -> Doc<> parens :: Doc -> Docparens (disp :: Text a => a -> Docdisp os :: OSos)
ppConfVar (Arch arch) = text :: String -> Doctext "arch" (<>) :: Doc -> Doc -> Doc<> parens :: Doc -> Docparens (disp :: Text a => a -> Docdisp arch :: Archarch)
ppConfVar (Flag name) = text :: String -> Doctext "flag" (<>) :: Doc -> Doc -> Doc<> parens :: Doc -> Docparens (ppFlagName :: FlagName -> DocppFlagName name :: FlagNamename)
ppConfVar (Impl c v) = text :: String -> Doctext "impl" (<>) :: Doc -> Doc -> Doc<> parens :: Doc -> Docparens (disp :: Text a => a -> Docdisp c :: Condition ConfVarc (<+>) :: Doc -> Doc -> Doc<+> disp :: Text a => a -> Docdisp v :: VersionRangev)
ppFlagName :: FlagName -> Doc
ppFlagName (FlagName name) = text :: String -> Doctext name :: FlagNamename
ppCondTree :: CondTree ConfVar [Dependency] a -> Maybe a -> (a -> Maybe a -> Doc) -> Doc
ppCondTree ct@(CondNode it deps ifs) mbIt ppIt =
let res = ppDeps :: [Dependency] -> DocppDeps deps :: [Dependency]deps
($+$) :: Doc -> Doc -> Doc$+$ (vcat :: [Doc] -> Docvcat ($) :: (a -> b) -> a -> b$ map :: (a -> b) -> [a] -> [b]map ppIf ::
(Condition ConfVar,
CondTree ConfVar [Dependency] a,
Maybe (CondTree ConfVar [Dependency] a))
-> DocppIf ifs ::
[(Condition ConfVar,
CondTree ConfVar [Dependency] a,
Maybe (CondTree ConfVar [Dependency] a))]ifs)
($+$) :: Doc -> Doc -> Doc$+$ ppIt :: a -> Maybe a -> DocppIt it :: ait mbIt :: Maybe ambIt
in if isJust :: Maybe a -> BoolisJust mbIt :: Maybe ambIt (&&) :: Bool -> Bool -> Bool&& isEmpty :: Doc -> BoolisEmpty res :: Docres
then ppCondTree ::
CondTree ConfVar [Dependency] a
-> Maybe a
-> (a -> Maybe a -> Doc)
-> DocppCondTree ct :: CondTree ConfVar [Dependency] act Nothing :: Maybe aNothing ppIt :: a -> Maybe a -> DocppIt
else res :: Docres
where
ppIf (c,thenTree,mElseTree) =
((emptyLine :: Doc -> DocemptyLine ($) :: (a -> b) -> a -> b$ text :: String -> Doctext "if" (<+>) :: Doc -> Doc -> Doc<+> ppCondition :: Condition ConfVar -> DocppCondition c :: Condition ConfVarc) ($$) :: Doc -> Doc -> Doc$$
nest :: Int -> Doc -> Docnest indentWith :: IntindentWith (ppCondTree ::
CondTree ConfVar [Dependency] a
-> Maybe a
-> (a -> Maybe a -> Doc)
-> DocppCondTree thenTree :: CondTree ConfVar [Dependency] athenTree
(if simplifiedPrinting :: BoolsimplifiedPrinting then (Just :: a -> Maybe aJust it :: ait) else Nothing :: Maybe aNothing) ppIt :: a -> Maybe a -> DocppIt))
($+$) :: Doc -> Doc -> Doc$+$ (if isNothing :: Maybe a -> BoolisNothing mElseTree :: Maybe (CondTree ConfVar [Dependency] a)mElseTree
then empty :: Docempty
else text :: String -> Doctext "else"
($$) :: Doc -> Doc -> Doc$$ nest :: Int -> Doc -> Docnest indentWith :: IntindentWith (ppCondTree ::
CondTree ConfVar [Dependency] a
-> Maybe a
-> (a -> Maybe a -> Doc)
-> DocppCondTree (fromJust :: Maybe a -> afromJust mElseTree :: Maybe (CondTree ConfVar [Dependency] a)mElseTree)
(if simplifiedPrinting :: BoolsimplifiedPrinting then (Just :: a -> Maybe aJust it :: ait) else Nothing :: Maybe aNothing) ppIt :: a -> Maybe a -> DocppIt))
ppDeps :: [Dependency] -> Doc
ppDeps [] = empty :: Docempty
ppDeps deps =
text :: String -> Doctext "build-depends:" (<+>) :: Doc -> Doc -> Doc<+> fsep :: [Doc] -> Docfsep (punctuate :: Doc -> [Doc] -> [Doc]punctuate comma :: Doccomma (map :: (a -> b) -> [a] -> [b]map disp :: Text a => a -> Docdisp deps :: [Dependency]deps))
emptyLine :: Doc -> Doc
emptyLine d = text :: String -> Doctext " " ($+$) :: Doc -> Doc -> Doc$+$ d :: Docd