{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE CPP #-}
module Hpack.Render (
renderPackage
, renderPackageWith
, defaultRenderSettings
, RenderSettings(..)
, Alignment(..)
, CommaStyle(..)
#ifdef TEST
, renderConditional
, renderDependencies
, renderLibraryFields
, renderExecutableFields
, renderFlag
, renderSourceRepository
, renderDirectories
, formatDescription
#endif
) where
import Control.Monad
import Data.Char
import Data.Maybe
import Data.List
import Data.Map.Lazy (Map)
import qualified Data.Map.Lazy as Map
import Hpack.Util
import Hpack.Config
import Hpack.Render.Hints
import Hpack.Render.Dsl
renderPackage :: [String] -> Package -> String
renderPackage :: [FilePath] -> Package -> FilePath
renderPackage [FilePath]
oldCabalFile = RenderSettings
-> Alignment
-> [FilePath]
-> [(FilePath, [FilePath])]
-> Package
-> FilePath
renderPackageWith RenderSettings
settings Alignment
alignment [FilePath]
formattingHintsFieldOrder [(FilePath, [FilePath])]
formattingHintsSectionsFieldOrder
where
FormattingHints{[FilePath]
[(FilePath, [FilePath])]
Maybe Alignment
RenderSettings
formattingHintsRenderSettings :: FormattingHints -> RenderSettings
formattingHintsAlignment :: FormattingHints -> Maybe Alignment
formattingHintsSectionsFieldOrder :: FormattingHints -> [(FilePath, [FilePath])]
formattingHintsFieldOrder :: FormattingHints -> [FilePath]
formattingHintsRenderSettings :: RenderSettings
formattingHintsAlignment :: Maybe Alignment
formattingHintsSectionsFieldOrder :: [(FilePath, [FilePath])]
formattingHintsFieldOrder :: [FilePath]
..} = [FilePath] -> FormattingHints
sniffFormattingHints [FilePath]
oldCabalFile
alignment :: Alignment
alignment = Alignment -> Maybe Alignment -> Alignment
forall a. a -> Maybe a -> a
fromMaybe Alignment
16 Maybe Alignment
formattingHintsAlignment
settings :: RenderSettings
settings = RenderSettings
formattingHintsRenderSettings
renderPackageWith :: RenderSettings -> Alignment -> [String] -> [(String, [String])] -> Package -> String
renderPackageWith :: RenderSettings
-> Alignment
-> [FilePath]
-> [(FilePath, [FilePath])]
-> Package
-> FilePath
renderPackageWith RenderSettings
settings Alignment
headerFieldsAlignment [FilePath]
existingFieldOrder [(FilePath, [FilePath])]
sectionsFieldOrder Package{FilePath
[FilePath]
[Path]
[Flag]
[Verbatim]
Maybe FilePath
Maybe SourceRepository
Maybe (Section Library)
Maybe CustomSetup
Map FilePath (Section Executable)
Map FilePath (Section Library)
BuildType
packageVerbatim :: Package -> [Verbatim]
packageBenchmarks :: Package -> Map FilePath (Section Executable)
packageTests :: Package -> Map FilePath (Section Executable)
packageExecutables :: Package -> Map FilePath (Section Executable)
packageInternalLibraries :: Package -> Map FilePath (Section Library)
packageLibrary :: Package -> Maybe (Section Library)
packageCustomSetup :: Package -> Maybe CustomSetup
packageSourceRepository :: Package -> Maybe SourceRepository
packageDataDir :: Package -> Maybe FilePath
packageDataFiles :: Package -> [Path]
packageExtraDocFiles :: Package -> [Path]
packageExtraSourceFiles :: Package -> [Path]
packageFlags :: Package -> [Flag]
packageTestedWith :: Package -> [FilePath]
packageLicenseFile :: Package -> [FilePath]
packageLicense :: Package -> Maybe FilePath
packageBuildType :: Package -> BuildType
packageCopyright :: Package -> [FilePath]
packageMaintainer :: Package -> [FilePath]
packageAuthor :: Package -> [FilePath]
packageStability :: Package -> Maybe FilePath
packageCategory :: Package -> Maybe FilePath
packageBugReports :: Package -> Maybe FilePath
packageHomepage :: Package -> Maybe FilePath
packageDescription :: Package -> Maybe FilePath
packageSynopsis :: Package -> Maybe FilePath
packageVersion :: Package -> FilePath
packageName :: Package -> FilePath
packageVerbatim :: [Verbatim]
packageBenchmarks :: Map FilePath (Section Executable)
packageTests :: Map FilePath (Section Executable)
packageExecutables :: Map FilePath (Section Executable)
packageInternalLibraries :: Map FilePath (Section Library)
packageLibrary :: Maybe (Section Library)
packageCustomSetup :: Maybe CustomSetup
packageSourceRepository :: Maybe SourceRepository
packageDataDir :: Maybe FilePath
packageDataFiles :: [Path]
packageExtraDocFiles :: [Path]
packageExtraSourceFiles :: [Path]
packageFlags :: [Flag]
packageTestedWith :: [FilePath]
packageLicenseFile :: [FilePath]
packageLicense :: Maybe FilePath
packageBuildType :: BuildType
packageCopyright :: [FilePath]
packageMaintainer :: [FilePath]
packageAuthor :: [FilePath]
packageStability :: Maybe FilePath
packageCategory :: Maybe FilePath
packageBugReports :: Maybe FilePath
packageHomepage :: Maybe FilePath
packageDescription :: Maybe FilePath
packageSynopsis :: Maybe FilePath
packageVersion :: FilePath
packageName :: FilePath
..} = FilePath -> [FilePath] -> FilePath
forall a. [a] -> [[a]] -> [a]
intercalate FilePath
"\n" ([FilePath] -> FilePath
unlines [FilePath]
header FilePath -> [FilePath] -> [FilePath]
forall a. a -> [a] -> [a]
: [FilePath]
chunks)
where
chunks :: [String]
chunks :: [FilePath]
chunks = ([FilePath] -> FilePath) -> [[FilePath]] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map [FilePath] -> FilePath
unlines ([[FilePath]] -> [FilePath])
-> ([Element] -> [[FilePath]]) -> [Element] -> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([FilePath] -> Bool) -> [[FilePath]] -> [[FilePath]]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool) -> ([FilePath] -> Bool) -> [FilePath] -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null) ([[FilePath]] -> [[FilePath]])
-> ([Element] -> [[FilePath]]) -> [Element] -> [[FilePath]]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Element -> [FilePath]) -> [Element] -> [[FilePath]]
forall a b. (a -> b) -> [a] -> [b]
map (RenderSettings -> Nesting -> Element -> [FilePath]
render RenderSettings
settings Nesting
0) ([Element] -> [FilePath]) -> [Element] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ [(FilePath, [FilePath])] -> [Element] -> [Element]
sortStanzaFields [(FilePath, [FilePath])]
sectionsFieldOrder [Element]
stanzas
header :: [String]
header :: [FilePath]
header = (Element -> [FilePath]) -> [Element] -> [FilePath]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (RenderSettings -> Nesting -> Element -> [FilePath]
render RenderSettings
settings {renderSettingsFieldAlignment :: Alignment
renderSettingsFieldAlignment = Alignment
headerFieldsAlignment} Nesting
0) [Element]
packageFields
packageFields :: [Element]
packageFields :: [Element]
packageFields = [Verbatim] -> [Element] -> [Element]
addVerbatim [Verbatim]
packageVerbatim ([Element] -> [Element])
-> ([Element] -> [Element]) -> [Element] -> [Element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> [Element] -> [Element]
sortFieldsBy [FilePath]
existingFieldOrder ([Element] -> [Element]) -> [Element] -> [Element]
forall a b. (a -> b) -> a -> b
$
[Element]
headerFields [Element] -> [Element] -> [Element]
forall a. [a] -> [a] -> [a]
++ [
FilePath -> Value -> Element
Field FilePath
"tested-with" (Value -> Element) -> Value -> Element
forall a b. (a -> b) -> a -> b
$ [FilePath] -> Value
CommaSeparatedList [FilePath]
packageTestedWith
, FilePath -> Value -> Element
Field FilePath
"extra-source-files" ([Path] -> Value
renderPaths [Path]
packageExtraSourceFiles)
, FilePath -> Value -> Element
Field FilePath
"extra-doc-files" ([Path] -> Value
renderPaths [Path]
packageExtraDocFiles)
, FilePath -> Value -> Element
Field FilePath
"data-files" ([Path] -> Value
renderPaths [Path]
packageDataFiles)
] [Element] -> [Element] -> [Element]
forall a. [a] -> [a] -> [a]
++ [Element] -> (FilePath -> [Element]) -> Maybe FilePath -> [Element]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (Element -> [Element]
forall (m :: * -> *) a. Monad m => a -> m a
return (Element -> [Element])
-> (FilePath -> Element) -> FilePath -> [Element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Value -> Element
Field FilePath
"data-dir" (Value -> Element) -> (FilePath -> Value) -> FilePath -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Value
Literal) Maybe FilePath
packageDataDir
sourceRepository :: [Element]
sourceRepository :: [Element]
sourceRepository = [Element]
-> (SourceRepository -> [Element])
-> Maybe SourceRepository
-> [Element]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (Element -> [Element]
forall (m :: * -> *) a. Monad m => a -> m a
return (Element -> [Element])
-> (SourceRepository -> Element) -> SourceRepository -> [Element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SourceRepository -> Element
renderSourceRepository) Maybe SourceRepository
packageSourceRepository
customSetup :: [Element]
customSetup :: [Element]
customSetup = [Element]
-> (CustomSetup -> [Element]) -> Maybe CustomSetup -> [Element]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (Element -> [Element]
forall (m :: * -> *) a. Monad m => a -> m a
return (Element -> [Element])
-> (CustomSetup -> Element) -> CustomSetup -> [Element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CustomSetup -> Element
renderCustomSetup) Maybe CustomSetup
packageCustomSetup
library :: [Element]
library :: [Element]
library = [Element]
-> (Section Library -> [Element])
-> Maybe (Section Library)
-> [Element]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (Element -> [Element]
forall (m :: * -> *) a. Monad m => a -> m a
return (Element -> [Element])
-> (Section Library -> Element) -> Section Library -> [Element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Section Library -> Element
renderLibrary) Maybe (Section Library)
packageLibrary
stanzas :: [Element]
stanzas :: [Element]
stanzas = [[Element]] -> [Element]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [
[Element]
sourceRepository
, [Element]
customSetup
, (Flag -> Element) -> [Flag] -> [Element]
forall a b. (a -> b) -> [a] -> [b]
map Flag -> Element
renderFlag [Flag]
packageFlags
, [Element]
library
, Map FilePath (Section Library) -> [Element]
renderInternalLibraries Map FilePath (Section Library)
packageInternalLibraries
, Map FilePath (Section Executable) -> [Element]
renderExecutables Map FilePath (Section Executable)
packageExecutables
, Map FilePath (Section Executable) -> [Element]
renderTests Map FilePath (Section Executable)
packageTests
, Map FilePath (Section Executable) -> [Element]
renderBenchmarks Map FilePath (Section Executable)
packageBenchmarks
]
headerFields :: [Element]
headerFields :: [Element]
headerFields = ((FilePath, Maybe FilePath) -> Maybe Element)
-> [(FilePath, Maybe FilePath)] -> [Element]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe (\(FilePath
name, Maybe FilePath
value) -> FilePath -> Value -> Element
Field FilePath
name (Value -> Element) -> (FilePath -> Value) -> FilePath -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Value
Literal (FilePath -> Element) -> Maybe FilePath -> Maybe Element
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe FilePath
value) ([(FilePath, Maybe FilePath)] -> [Element])
-> [(FilePath, Maybe FilePath)] -> [Element]
forall a b. (a -> b) -> a -> b
$ [
(FilePath
"name", FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
packageName)
, (FilePath
"version", FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
packageVersion)
, (FilePath
"synopsis", Maybe FilePath
packageSynopsis)
, (FilePath
"description", (Alignment -> FilePath -> FilePath
formatDescription Alignment
headerFieldsAlignment (FilePath -> FilePath) -> Maybe FilePath -> Maybe FilePath
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe FilePath
packageDescription))
, (FilePath
"category", Maybe FilePath
packageCategory)
, (FilePath
"stability", Maybe FilePath
packageStability)
, (FilePath
"homepage", Maybe FilePath
packageHomepage)
, (FilePath
"bug-reports", Maybe FilePath
packageBugReports)
, (FilePath
"author", [FilePath] -> Maybe FilePath
formatList [FilePath]
packageAuthor)
, (FilePath
"maintainer", [FilePath] -> Maybe FilePath
formatList [FilePath]
packageMaintainer)
, (FilePath
"copyright", [FilePath] -> Maybe FilePath
formatList [FilePath]
packageCopyright)
, (FilePath
"license", Maybe FilePath
packageLicense)
, case [FilePath]
packageLicenseFile of
[FilePath
file] -> (FilePath
"license-file", FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just FilePath
file)
[FilePath]
files -> (FilePath
"license-files", [FilePath] -> Maybe FilePath
formatList [FilePath]
files)
, (FilePath
"build-type", FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just (BuildType -> FilePath
forall a. Show a => a -> FilePath
show BuildType
packageBuildType))
]
formatList :: [String] -> Maybe String
formatList :: [FilePath] -> Maybe FilePath
formatList [FilePath]
xs = Bool -> Maybe ()
forall (f :: * -> *). Alternative f => Bool -> f ()
guard (Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ [FilePath] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [FilePath]
xs) Maybe () -> Maybe FilePath -> Maybe FilePath
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> (FilePath -> Maybe FilePath
forall a. a -> Maybe a
Just (FilePath -> Maybe FilePath) -> FilePath -> Maybe FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> [FilePath] -> FilePath
forall a. [a] -> [[a]] -> [a]
intercalate FilePath
separator [FilePath]
xs)
where
separator :: FilePath
separator = let Alignment Int
n = Alignment
headerFieldsAlignment in FilePath
",\n" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Int -> Char -> FilePath
forall a. Int -> a -> [a]
replicate Int
n Char
' '
sortStanzaFields :: [(String, [String])] -> [Element] -> [Element]
sortStanzaFields :: [(FilePath, [FilePath])] -> [Element] -> [Element]
sortStanzaFields [(FilePath, [FilePath])]
sectionsFieldOrder = [Element] -> [Element]
go
where
go :: [Element] -> [Element]
go [Element]
sections = case [Element]
sections of
[] -> []
Stanza FilePath
name [Element]
fields : [Element]
xs | Just [FilePath]
fieldOrder <- FilePath -> [(FilePath, [FilePath])] -> Maybe [FilePath]
forall a b. Eq a => a -> [(a, b)] -> Maybe b
lookup FilePath
name [(FilePath, [FilePath])]
sectionsFieldOrder -> FilePath -> [Element] -> Element
Stanza FilePath
name ([FilePath] -> [Element] -> [Element]
sortFieldsBy [FilePath]
fieldOrder [Element]
fields) Element -> [Element] -> [Element]
forall a. a -> [a] -> [a]
: [Element] -> [Element]
go [Element]
xs
Element
x : [Element]
xs -> Element
x Element -> [Element] -> [Element]
forall a. a -> [a] -> [a]
: [Element] -> [Element]
go [Element]
xs
formatDescription :: Alignment -> String -> String
formatDescription :: Alignment -> FilePath -> FilePath
formatDescription (Alignment Int
alignment) FilePath
description = case (FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map FilePath -> FilePath
emptyLineToDot ([FilePath] -> [FilePath]) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ FilePath -> [FilePath]
lines FilePath
description of
FilePath
x : [FilePath]
xs -> FilePath -> [FilePath] -> FilePath
forall a. [a] -> [[a]] -> [a]
intercalate FilePath
"\n" (FilePath
x FilePath -> [FilePath] -> [FilePath]
forall a. a -> [a] -> [a]
: (FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath
indentation FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++) [FilePath]
xs)
[] -> FilePath
""
where
n :: Int
n = Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
alignment (FilePath -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length (FilePath
"description: " :: String))
indentation :: FilePath
indentation = Int -> Char -> FilePath
forall a. Int -> a -> [a]
replicate Int
n Char
' '
emptyLineToDot :: FilePath -> FilePath
emptyLineToDot FilePath
xs
| FilePath -> Bool
isEmptyLine FilePath
xs = FilePath
"."
| Bool
otherwise = FilePath
xs
isEmptyLine :: FilePath -> Bool
isEmptyLine = (Char -> Bool) -> FilePath -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Char -> Bool
isSpace
renderSourceRepository :: SourceRepository -> Element
renderSourceRepository :: SourceRepository -> Element
renderSourceRepository SourceRepository{FilePath
Maybe FilePath
sourceRepositorySubdir :: SourceRepository -> Maybe FilePath
sourceRepositoryUrl :: SourceRepository -> FilePath
sourceRepositorySubdir :: Maybe FilePath
sourceRepositoryUrl :: FilePath
..} = FilePath -> [Element] -> Element
Stanza FilePath
"source-repository head" [
FilePath -> Value -> Element
Field FilePath
"type" Value
"git"
, FilePath -> Value -> Element
Field FilePath
"location" (FilePath -> Value
Literal FilePath
sourceRepositoryUrl)
, FilePath -> Value -> Element
Field FilePath
"subdir" (Value -> (FilePath -> Value) -> Maybe FilePath -> Value
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Value
"" FilePath -> Value
Literal Maybe FilePath
sourceRepositorySubdir)
]
renderFlag :: Flag -> Element
renderFlag :: Flag -> Element
renderFlag Flag {Bool
FilePath
Maybe FilePath
flagDefault :: Flag -> Bool
flagManual :: Flag -> Bool
flagDescription :: Flag -> Maybe FilePath
flagName :: Flag -> FilePath
flagDefault :: Bool
flagManual :: Bool
flagDescription :: Maybe FilePath
flagName :: FilePath
..} = FilePath -> [Element] -> Element
Stanza (FilePath
"flag " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
flagName) ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ [Element]
description [Element] -> [Element] -> [Element]
forall a. [a] -> [a] -> [a]
++ [
FilePath -> Value -> Element
Field FilePath
"manual" (FilePath -> Value
Literal (FilePath -> Value) -> FilePath -> Value
forall a b. (a -> b) -> a -> b
$ Bool -> FilePath
forall a. Show a => a -> FilePath
show Bool
flagManual)
, FilePath -> Value -> Element
Field FilePath
"default" (FilePath -> Value
Literal (FilePath -> Value) -> FilePath -> Value
forall a b. (a -> b) -> a -> b
$ Bool -> FilePath
forall a. Show a => a -> FilePath
show Bool
flagDefault)
]
where
description :: [Element]
description = [Element] -> (FilePath -> [Element]) -> Maybe FilePath -> [Element]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (Element -> [Element]
forall (m :: * -> *) a. Monad m => a -> m a
return (Element -> [Element])
-> (FilePath -> Element) -> FilePath -> [Element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Value -> Element
Field FilePath
"description" (Value -> Element) -> (FilePath -> Value) -> FilePath -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Value
Literal) Maybe FilePath
flagDescription
renderInternalLibraries :: Map String (Section Library) -> [Element]
renderInternalLibraries :: Map FilePath (Section Library) -> [Element]
renderInternalLibraries = ((FilePath, Section Library) -> Element)
-> [(FilePath, Section Library)] -> [Element]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath, Section Library) -> Element
renderInternalLibrary ([(FilePath, Section Library)] -> [Element])
-> (Map FilePath (Section Library)
-> [(FilePath, Section Library)])
-> Map FilePath (Section Library)
-> [Element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map FilePath (Section Library) -> [(FilePath, Section Library)]
forall k a. Map k a -> [(k, a)]
Map.toList
renderInternalLibrary :: (String, Section Library) -> Element
renderInternalLibrary :: (FilePath, Section Library) -> Element
renderInternalLibrary (FilePath
name, Section Library
sect) =
FilePath -> [Element] -> Element
Stanza (FilePath
"library " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
name) (Section Library -> [Element]
renderLibrarySection Section Library
sect)
renderExecutables :: Map String (Section Executable) -> [Element]
renderExecutables :: Map FilePath (Section Executable) -> [Element]
renderExecutables = ((FilePath, Section Executable) -> Element)
-> [(FilePath, Section Executable)] -> [Element]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath, Section Executable) -> Element
renderExecutable ([(FilePath, Section Executable)] -> [Element])
-> (Map FilePath (Section Executable)
-> [(FilePath, Section Executable)])
-> Map FilePath (Section Executable)
-> [Element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map FilePath (Section Executable)
-> [(FilePath, Section Executable)]
forall k a. Map k a -> [(k, a)]
Map.toList
renderExecutable :: (String, Section Executable) -> Element
renderExecutable :: (FilePath, Section Executable) -> Element
renderExecutable (FilePath
name, sect :: Section Executable
sect@(Section Executable -> Executable
forall a. Section a -> a
sectionData -> Executable{[Module]
Maybe FilePath
executableGeneratedModules :: Executable -> [Module]
executableOtherModules :: Executable -> [Module]
executableMain :: Executable -> Maybe FilePath
executableGeneratedModules :: [Module]
executableOtherModules :: [Module]
executableMain :: Maybe FilePath
..})) =
FilePath -> [Element] -> Element
Stanza (FilePath
"executable " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
name) ([Element] -> Section Executable -> [Element]
renderExecutableSection [] Section Executable
sect)
renderTests :: Map String (Section Executable) -> [Element]
renderTests :: Map FilePath (Section Executable) -> [Element]
renderTests = ((FilePath, Section Executable) -> Element)
-> [(FilePath, Section Executable)] -> [Element]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath, Section Executable) -> Element
renderTest ([(FilePath, Section Executable)] -> [Element])
-> (Map FilePath (Section Executable)
-> [(FilePath, Section Executable)])
-> Map FilePath (Section Executable)
-> [Element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map FilePath (Section Executable)
-> [(FilePath, Section Executable)]
forall k a. Map k a -> [(k, a)]
Map.toList
renderTest :: (String, Section Executable) -> Element
renderTest :: (FilePath, Section Executable) -> Element
renderTest (FilePath
name, Section Executable
sect) =
FilePath -> [Element] -> Element
Stanza (FilePath
"test-suite " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
name)
([Element] -> Section Executable -> [Element]
renderExecutableSection [FilePath -> Value -> Element
Field FilePath
"type" Value
"exitcode-stdio-1.0"] Section Executable
sect)
renderBenchmarks :: Map String (Section Executable) -> [Element]
renderBenchmarks :: Map FilePath (Section Executable) -> [Element]
renderBenchmarks = ((FilePath, Section Executable) -> Element)
-> [(FilePath, Section Executable)] -> [Element]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath, Section Executable) -> Element
renderBenchmark ([(FilePath, Section Executable)] -> [Element])
-> (Map FilePath (Section Executable)
-> [(FilePath, Section Executable)])
-> Map FilePath (Section Executable)
-> [Element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map FilePath (Section Executable)
-> [(FilePath, Section Executable)]
forall k a. Map k a -> [(k, a)]
Map.toList
renderBenchmark :: (String, Section Executable) -> Element
renderBenchmark :: (FilePath, Section Executable) -> Element
renderBenchmark (FilePath
name, Section Executable
sect) =
FilePath -> [Element] -> Element
Stanza (FilePath
"benchmark " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
name)
([Element] -> Section Executable -> [Element]
renderExecutableSection [FilePath -> Value -> Element
Field FilePath
"type" Value
"exitcode-stdio-1.0"] Section Executable
sect)
renderExecutableSection :: [Element] -> Section Executable -> [Element]
renderExecutableSection :: [Element] -> Section Executable -> [Element]
renderExecutableSection [Element]
extraFields = (Executable -> [Element])
-> [Element] -> [Element] -> Section Executable -> [Element]
forall a.
(a -> [Element])
-> [Element] -> [Element] -> Section a -> [Element]
renderSection Executable -> [Element]
renderExecutableFields [Element]
extraFields [Element
defaultLanguage]
renderExecutableFields :: Executable -> [Element]
renderExecutableFields :: Executable -> [Element]
renderExecutableFields Executable{[Module]
Maybe FilePath
executableGeneratedModules :: [Module]
executableOtherModules :: [Module]
executableMain :: Maybe FilePath
executableGeneratedModules :: Executable -> [Module]
executableOtherModules :: Executable -> [Module]
executableMain :: Executable -> Maybe FilePath
..} = [Element]
mainIs [Element] -> [Element] -> [Element]
forall a. [a] -> [a] -> [a]
++ [Element
otherModules, Element
generatedModules]
where
mainIs :: [Element]
mainIs = [Element] -> (FilePath -> [Element]) -> Maybe FilePath -> [Element]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (Element -> [Element]
forall (m :: * -> *) a. Monad m => a -> m a
return (Element -> [Element])
-> (FilePath -> Element) -> FilePath -> [Element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Value -> Element
Field FilePath
"main-is" (Value -> Element) -> (FilePath -> Value) -> FilePath -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Value
Literal) Maybe FilePath
executableMain
otherModules :: Element
otherModules = [Module] -> Element
renderOtherModules [Module]
executableOtherModules
generatedModules :: Element
generatedModules = [Module] -> Element
renderGeneratedModules [Module]
executableGeneratedModules
renderCustomSetup :: CustomSetup -> Element
renderCustomSetup :: CustomSetup -> Element
renderCustomSetup CustomSetup{Dependencies
customSetupDependencies :: CustomSetup -> Dependencies
customSetupDependencies :: Dependencies
..} =
FilePath -> [Element] -> Element
Stanza FilePath
"custom-setup" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ FilePath -> Dependencies -> [Element]
renderDependencies FilePath
"setup-depends" Dependencies
customSetupDependencies
renderLibrary :: Section Library -> Element
renderLibrary :: Section Library -> Element
renderLibrary Section Library
sect = FilePath -> [Element] -> Element
Stanza FilePath
"library" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ Section Library -> [Element]
renderLibrarySection Section Library
sect
renderLibrarySection :: Section Library -> [Element]
renderLibrarySection :: Section Library -> [Element]
renderLibrarySection = (Library -> [Element])
-> [Element] -> [Element] -> Section Library -> [Element]
forall a.
(a -> [Element])
-> [Element] -> [Element] -> Section a -> [Element]
renderSection Library -> [Element]
renderLibraryFields [] [Element
defaultLanguage]
renderLibraryFields :: Library -> [Element]
renderLibraryFields :: Library -> [Element]
renderLibraryFields Library{[FilePath]
[Module]
Maybe Bool
Maybe FilePath
librarySignatures :: Library -> [FilePath]
libraryReexportedModules :: Library -> [FilePath]
libraryGeneratedModules :: Library -> [Module]
libraryOtherModules :: Library -> [Module]
libraryExposedModules :: Library -> [Module]
libraryVisibility :: Library -> Maybe FilePath
libraryExposed :: Library -> Maybe Bool
librarySignatures :: [FilePath]
libraryReexportedModules :: [FilePath]
libraryGeneratedModules :: [Module]
libraryOtherModules :: [Module]
libraryExposedModules :: [Module]
libraryVisibility :: Maybe FilePath
libraryExposed :: Maybe Bool
..} =
[Element] -> (Bool -> [Element]) -> Maybe Bool -> [Element]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (Element -> [Element]
forall (m :: * -> *) a. Monad m => a -> m a
return (Element -> [Element]) -> (Bool -> Element) -> Bool -> [Element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Element
renderExposed) Maybe Bool
libraryExposed [Element] -> [Element] -> [Element]
forall a. [a] -> [a] -> [a]
++
[Element] -> (FilePath -> [Element]) -> Maybe FilePath -> [Element]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (Element -> [Element]
forall (m :: * -> *) a. Monad m => a -> m a
return (Element -> [Element])
-> (FilePath -> Element) -> FilePath -> [Element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Element
renderVisibility) Maybe FilePath
libraryVisibility [Element] -> [Element] -> [Element]
forall a. [a] -> [a] -> [a]
++ [
[Module] -> Element
renderExposedModules [Module]
libraryExposedModules
, [Module] -> Element
renderOtherModules [Module]
libraryOtherModules
, [Module] -> Element
renderGeneratedModules [Module]
libraryGeneratedModules
, [FilePath] -> Element
renderReexportedModules [FilePath]
libraryReexportedModules
, [FilePath] -> Element
renderSignatures [FilePath]
librarySignatures
]
renderExposed :: Bool -> Element
renderExposed :: Bool -> Element
renderExposed = FilePath -> Value -> Element
Field FilePath
"exposed" (Value -> Element) -> (Bool -> Value) -> Bool -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Value
Literal (FilePath -> Value) -> (Bool -> FilePath) -> Bool -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> FilePath
forall a. Show a => a -> FilePath
show
renderVisibility :: String -> Element
renderVisibility :: FilePath -> Element
renderVisibility = FilePath -> Value -> Element
Field FilePath
"visibility" (Value -> Element) -> (FilePath -> Value) -> FilePath -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Value
Literal
renderSection :: (a -> [Element]) -> [Element] -> [Element] -> Section a -> [Element]
renderSection :: forall a.
(a -> [Element])
-> [Element] -> [Element] -> Section a -> [Element]
renderSection a -> [Element]
renderSectionData [Element]
extraFieldsStart [Element]
extraFieldsEnd Section{a
[FilePath]
[Path]
[Conditional (Section a)]
[Verbatim]
Maybe Bool
Map BuildTool DependencyVersion
Dependencies
SystemBuildTools
sectionVerbatim :: forall a. Section a -> [Verbatim]
sectionSystemBuildTools :: forall a. Section a -> SystemBuildTools
sectionBuildTools :: forall a. Section a -> Map BuildTool DependencyVersion
sectionConditionals :: forall a. Section a -> [Conditional (Section a)]
sectionBuildable :: forall a. Section a -> Maybe Bool
sectionLdOptions :: forall a. Section a -> [FilePath]
sectionInstallIncludes :: forall a. Section a -> [FilePath]
sectionIncludeDirs :: forall a. Section a -> [FilePath]
sectionFrameworks :: forall a. Section a -> [FilePath]
sectionExtraFrameworksDirs :: forall a. Section a -> [FilePath]
sectionExtraLibraries :: forall a. Section a -> [FilePath]
sectionExtraLibDirs :: forall a. Section a -> [FilePath]
sectionJsSources :: forall a. Section a -> [Path]
sectionCxxSources :: forall a. Section a -> [Path]
sectionCxxOptions :: forall a. Section a -> [FilePath]
sectionCSources :: forall a. Section a -> [Path]
sectionCcOptions :: forall a. Section a -> [FilePath]
sectionCppOptions :: forall a. Section a -> [FilePath]
sectionGhcjsOptions :: forall a. Section a -> [FilePath]
sectionGhcProfOptions :: forall a. Section a -> [FilePath]
sectionGhcOptions :: forall a. Section a -> [FilePath]
sectionOtherExtensions :: forall a. Section a -> [FilePath]
sectionDefaultExtensions :: forall a. Section a -> [FilePath]
sectionPkgConfigDependencies :: forall a. Section a -> [FilePath]
sectionDependencies :: forall a. Section a -> Dependencies
sectionSourceDirs :: forall a. Section a -> [FilePath]
sectionVerbatim :: [Verbatim]
sectionSystemBuildTools :: SystemBuildTools
sectionBuildTools :: Map BuildTool DependencyVersion
sectionConditionals :: [Conditional (Section a)]
sectionBuildable :: Maybe Bool
sectionLdOptions :: [FilePath]
sectionInstallIncludes :: [FilePath]
sectionIncludeDirs :: [FilePath]
sectionFrameworks :: [FilePath]
sectionExtraFrameworksDirs :: [FilePath]
sectionExtraLibraries :: [FilePath]
sectionExtraLibDirs :: [FilePath]
sectionJsSources :: [Path]
sectionCxxSources :: [Path]
sectionCxxOptions :: [FilePath]
sectionCSources :: [Path]
sectionCcOptions :: [FilePath]
sectionCppOptions :: [FilePath]
sectionGhcjsOptions :: [FilePath]
sectionGhcProfOptions :: [FilePath]
sectionGhcOptions :: [FilePath]
sectionOtherExtensions :: [FilePath]
sectionDefaultExtensions :: [FilePath]
sectionPkgConfigDependencies :: [FilePath]
sectionDependencies :: Dependencies
sectionSourceDirs :: [FilePath]
sectionData :: a
sectionData :: forall a. Section a -> a
..} = [Verbatim] -> [Element] -> [Element]
addVerbatim [Verbatim]
sectionVerbatim ([Element] -> [Element]) -> [Element] -> [Element]
forall a b. (a -> b) -> a -> b
$
[Element]
extraFieldsStart
[Element] -> [Element] -> [Element]
forall a. [a] -> [a] -> [a]
++ a -> [Element]
renderSectionData a
sectionData [Element] -> [Element] -> [Element]
forall a. [a] -> [a] -> [a]
++ [
FilePath -> [FilePath] -> Element
renderDirectories FilePath
"hs-source-dirs" [FilePath]
sectionSourceDirs
, [FilePath] -> Element
renderDefaultExtensions [FilePath]
sectionDefaultExtensions
, [FilePath] -> Element
renderOtherExtensions [FilePath]
sectionOtherExtensions
, [FilePath] -> Element
renderGhcOptions [FilePath]
sectionGhcOptions
, [FilePath] -> Element
renderGhcProfOptions [FilePath]
sectionGhcProfOptions
, [FilePath] -> Element
renderGhcjsOptions [FilePath]
sectionGhcjsOptions
, [FilePath] -> Element
renderCppOptions [FilePath]
sectionCppOptions
, [FilePath] -> Element
renderCcOptions [FilePath]
sectionCcOptions
, [FilePath] -> Element
renderCxxOptions [FilePath]
sectionCxxOptions
, FilePath -> [FilePath] -> Element
renderDirectories FilePath
"include-dirs" [FilePath]
sectionIncludeDirs
, FilePath -> Value -> Element
Field FilePath
"install-includes" ([FilePath] -> Value
LineSeparatedList [FilePath]
sectionInstallIncludes)
, FilePath -> Value -> Element
Field FilePath
"c-sources" ([Path] -> Value
renderPaths [Path]
sectionCSources)
, FilePath -> Value -> Element
Field FilePath
"cxx-sources" ([Path] -> Value
renderPaths [Path]
sectionCxxSources)
, FilePath -> Value -> Element
Field FilePath
"js-sources" ([Path] -> Value
renderPaths [Path]
sectionJsSources)
, FilePath -> [FilePath] -> Element
renderDirectories FilePath
"extra-lib-dirs" [FilePath]
sectionExtraLibDirs
, FilePath -> Value -> Element
Field FilePath
"extra-libraries" ([FilePath] -> Value
LineSeparatedList [FilePath]
sectionExtraLibraries)
, FilePath -> [FilePath] -> Element
renderDirectories FilePath
"extra-frameworks-dirs" [FilePath]
sectionExtraFrameworksDirs
, FilePath -> Value -> Element
Field FilePath
"frameworks" ([FilePath] -> Value
LineSeparatedList [FilePath]
sectionFrameworks)
, [FilePath] -> Element
renderLdOptions [FilePath]
sectionLdOptions
, FilePath -> Value -> Element
Field FilePath
"pkgconfig-depends" ([FilePath] -> Value
CommaSeparatedList [FilePath]
sectionPkgConfigDependencies)
]
[Element] -> [Element] -> [Element]
forall a. [a] -> [a] -> [a]
++ Map BuildTool DependencyVersion -> SystemBuildTools -> [Element]
renderBuildTools Map BuildTool DependencyVersion
sectionBuildTools SystemBuildTools
sectionSystemBuildTools
[Element] -> [Element] -> [Element]
forall a. [a] -> [a] -> [a]
++ FilePath -> Dependencies -> [Element]
renderDependencies FilePath
"build-depends" Dependencies
sectionDependencies
[Element] -> [Element] -> [Element]
forall a. [a] -> [a] -> [a]
++ [Element] -> (Bool -> [Element]) -> Maybe Bool -> [Element]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] (Element -> [Element]
forall (m :: * -> *) a. Monad m => a -> m a
return (Element -> [Element]) -> (Bool -> Element) -> Bool -> [Element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> Element
renderBuildable) Maybe Bool
sectionBuildable
[Element] -> [Element] -> [Element]
forall a. [a] -> [a] -> [a]
++ (Conditional (Section a) -> Element)
-> [Conditional (Section a)] -> [Element]
forall a b. (a -> b) -> [a] -> [b]
map ((a -> [Element]) -> Conditional (Section a) -> Element
forall a. (a -> [Element]) -> Conditional (Section a) -> Element
renderConditional a -> [Element]
renderSectionData) [Conditional (Section a)]
sectionConditionals
[Element] -> [Element] -> [Element]
forall a. [a] -> [a] -> [a]
++ [Element]
extraFieldsEnd
addVerbatim :: [Verbatim] -> [Element] -> [Element]
addVerbatim :: [Verbatim] -> [Element] -> [Element]
addVerbatim [Verbatim]
verbatim [Element]
fields = [Verbatim] -> [Element] -> [Element]
filterVerbatim [Verbatim]
verbatim [Element]
fields [Element] -> [Element] -> [Element]
forall a. [a] -> [a] -> [a]
++ [Verbatim] -> [Element]
renderVerbatim [Verbatim]
verbatim
filterVerbatim :: [Verbatim] -> [Element] -> [Element]
filterVerbatim :: [Verbatim] -> [Element] -> [Element]
filterVerbatim [Verbatim]
verbatim = (Element -> Bool) -> [Element] -> [Element]
forall a. (a -> Bool) -> [a] -> [a]
filter Element -> Bool
p
where
p :: Element -> Bool
p :: Element -> Bool
p = \ case
Field FilePath
name Value
_ -> FilePath
name FilePath -> [FilePath] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` [FilePath]
fields
Element
_ -> Bool
True
fields :: [FilePath]
fields = (Verbatim -> [FilePath]) -> [Verbatim] -> [FilePath]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap Verbatim -> [FilePath]
verbatimFieldNames [Verbatim]
verbatim
verbatimFieldNames :: Verbatim -> [String]
verbatimFieldNames :: Verbatim -> [FilePath]
verbatimFieldNames Verbatim
verbatim = case Verbatim
verbatim of
VerbatimLiteral FilePath
_ -> []
VerbatimObject Map FilePath VerbatimValue
o -> Map FilePath VerbatimValue -> [FilePath]
forall k a. Map k a -> [k]
Map.keys Map FilePath VerbatimValue
o
renderVerbatim :: [Verbatim] -> [Element]
renderVerbatim :: [Verbatim] -> [Element]
renderVerbatim = (Verbatim -> [Element]) -> [Verbatim] -> [Element]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap ((Verbatim -> [Element]) -> [Verbatim] -> [Element])
-> (Verbatim -> [Element]) -> [Verbatim] -> [Element]
forall a b. (a -> b) -> a -> b
$ \ case
VerbatimLiteral FilePath
s -> [FilePath -> Element
Verbatim FilePath
s]
VerbatimObject Map FilePath VerbatimValue
o -> Map FilePath VerbatimValue -> [Element]
renderVerbatimObject Map FilePath VerbatimValue
o
renderVerbatimObject :: Map String VerbatimValue -> [Element]
renderVerbatimObject :: Map FilePath VerbatimValue -> [Element]
renderVerbatimObject = ((FilePath, VerbatimValue) -> Element)
-> [(FilePath, VerbatimValue)] -> [Element]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath, VerbatimValue) -> Element
renderPair ([(FilePath, VerbatimValue)] -> [Element])
-> (Map FilePath VerbatimValue -> [(FilePath, VerbatimValue)])
-> Map FilePath VerbatimValue
-> [Element]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map FilePath VerbatimValue -> [(FilePath, VerbatimValue)]
forall k a. Map k a -> [(k, a)]
Map.toList
where
renderPair :: (FilePath, VerbatimValue) -> Element
renderPair (FilePath
key, VerbatimValue
value) = case FilePath -> [FilePath]
lines (VerbatimValue -> FilePath
verbatimValueToString VerbatimValue
value) of
[FilePath
x] -> FilePath -> Value -> Element
Field FilePath
key (FilePath -> Value
Literal FilePath
x)
[FilePath]
xs -> FilePath -> Value -> Element
Field FilePath
key ([FilePath] -> Value
LineSeparatedList [FilePath]
xs)
renderConditional :: (a -> [Element]) -> Conditional (Section a) -> Element
renderConditional :: forall a. (a -> [Element]) -> Conditional (Section a) -> Element
renderConditional a -> [Element]
renderSectionData (Conditional Cond
condition Section a
sect Maybe (Section a)
mElse) = case Maybe (Section a)
mElse of
Maybe (Section a)
Nothing -> Element
if_
Just Section a
else_ -> Element -> Element -> Element
Group Element
if_ (FilePath -> [Element] -> Element
Stanza FilePath
"else" ([Element] -> Element) -> [Element] -> Element
forall a b. (a -> b) -> a -> b
$ (a -> [Element])
-> [Element] -> [Element] -> Section a -> [Element]
forall a.
(a -> [Element])
-> [Element] -> [Element] -> Section a -> [Element]
renderSection a -> [Element]
renderSectionData [] [] Section a
else_)
where
if_ :: Element
if_ = FilePath -> [Element] -> Element
Stanza (FilePath
"if " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ Cond -> FilePath
renderCond Cond
condition) ((a -> [Element])
-> [Element] -> [Element] -> Section a -> [Element]
forall a.
(a -> [Element])
-> [Element] -> [Element] -> Section a -> [Element]
renderSection a -> [Element]
renderSectionData [] [] Section a
sect)
renderCond :: Cond -> String
renderCond :: Cond -> FilePath
renderCond = \ case
CondExpression FilePath
c -> FilePath
c
CondBool Bool
True -> FilePath
"true"
CondBool Bool
False -> FilePath
"false"
defaultLanguage :: Element
defaultLanguage :: Element
defaultLanguage = FilePath -> Value -> Element
Field FilePath
"default-language" Value
"Haskell2010"
renderDirectories :: String -> [String] -> Element
renderDirectories :: FilePath -> [FilePath] -> Element
renderDirectories FilePath
name = FilePath -> Value -> Element
Field FilePath
name (Value -> Element)
-> ([FilePath] -> Value) -> [FilePath] -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> Value
LineSeparatedList ([FilePath] -> Value)
-> ([FilePath] -> [FilePath]) -> [FilePath] -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> [FilePath]
replaceDots
where
replaceDots :: [FilePath] -> [FilePath]
replaceDots = (FilePath -> FilePath) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map FilePath -> FilePath
forall {p}. (Eq p, IsString p) => p -> p
replaceDot
replaceDot :: p -> p
replaceDot p
xs = case p
xs of
p
"." -> p
"./"
p
_ -> p
xs
renderExposedModules :: [Module] -> Element
renderExposedModules :: [Module] -> Element
renderExposedModules = FilePath -> Value -> Element
Field FilePath
"exposed-modules" (Value -> Element) -> ([Module] -> Value) -> [Module] -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> Value
LineSeparatedList ([FilePath] -> Value)
-> ([Module] -> [FilePath]) -> [Module] -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Module -> FilePath) -> [Module] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map Module -> FilePath
unModule
renderOtherModules :: [Module] -> Element
renderOtherModules :: [Module] -> Element
renderOtherModules = FilePath -> Value -> Element
Field FilePath
"other-modules" (Value -> Element) -> ([Module] -> Value) -> [Module] -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> Value
LineSeparatedList ([FilePath] -> Value)
-> ([Module] -> [FilePath]) -> [Module] -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Module -> FilePath) -> [Module] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map Module -> FilePath
unModule
renderGeneratedModules :: [Module] -> Element
renderGeneratedModules :: [Module] -> Element
renderGeneratedModules = FilePath -> Value -> Element
Field FilePath
"autogen-modules" (Value -> Element) -> ([Module] -> Value) -> [Module] -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> Value
LineSeparatedList ([FilePath] -> Value)
-> ([Module] -> [FilePath]) -> [Module] -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Module -> FilePath) -> [Module] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map Module -> FilePath
unModule
renderReexportedModules :: [String] -> Element
renderReexportedModules :: [FilePath] -> Element
renderReexportedModules = FilePath -> Value -> Element
Field FilePath
"reexported-modules" (Value -> Element)
-> ([FilePath] -> Value) -> [FilePath] -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> Value
CommaSeparatedList
renderSignatures :: [String] -> Element
renderSignatures :: [FilePath] -> Element
renderSignatures = FilePath -> Value -> Element
Field FilePath
"signatures" (Value -> Element)
-> ([FilePath] -> Value) -> [FilePath] -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> Value
CommaSeparatedList
renderDependencies :: String -> Dependencies -> [Element]
renderDependencies :: FilePath -> Dependencies -> [Element]
renderDependencies FilePath
name Dependencies
deps = [
FilePath -> Value -> Element
Field FilePath
name ([FilePath] -> Value
CommaSeparatedList [FilePath]
renderedDeps)
, FilePath -> Value -> Element
Field FilePath
"mixins" ([FilePath] -> Value
CommaSeparatedList ([FilePath] -> Value) -> [FilePath] -> Value
forall a b. (a -> b) -> a -> b
$ [[FilePath]] -> [FilePath]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[FilePath]]
mixins)
]
where
([FilePath]
renderedDeps, [[FilePath]]
mixins) = [(FilePath, [FilePath])] -> ([FilePath], [[FilePath]])
forall a b. [(a, b)] -> ([a], [b])
unzip ([(FilePath, [FilePath])] -> ([FilePath], [[FilePath]]))
-> (Map FilePath DependencyInfo -> [(FilePath, [FilePath])])
-> Map FilePath DependencyInfo
-> ([FilePath], [[FilePath]])
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((FilePath, DependencyInfo) -> (FilePath, [FilePath]))
-> [(FilePath, DependencyInfo)] -> [(FilePath, [FilePath])]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath, DependencyInfo) -> (FilePath, [FilePath])
renderDependency ([(FilePath, DependencyInfo)] -> [(FilePath, [FilePath])])
-> (Map FilePath DependencyInfo -> [(FilePath, DependencyInfo)])
-> Map FilePath DependencyInfo
-> [(FilePath, [FilePath])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map FilePath DependencyInfo -> [(FilePath, DependencyInfo)]
forall k a. Map k a -> [(k, a)]
Map.toList (Map FilePath DependencyInfo -> ([FilePath], [[FilePath]]))
-> Map FilePath DependencyInfo -> ([FilePath], [[FilePath]])
forall a b. (a -> b) -> a -> b
$ Dependencies -> Map FilePath DependencyInfo
unDependencies Dependencies
deps
renderDependency :: (String, DependencyInfo) -> (String, [String])
renderDependency :: (FilePath, DependencyInfo) -> (FilePath, [FilePath])
renderDependency (FilePath
name, DependencyInfo [FilePath]
mixins DependencyVersion
version) = (
FilePath
name FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ DependencyVersion -> FilePath
renderVersion DependencyVersion
version
, [ FilePath
name FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
" " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
mixin | FilePath
mixin <- [FilePath]
mixins ]
)
renderVersion :: DependencyVersion -> String
renderVersion :: DependencyVersion -> FilePath
renderVersion (DependencyVersion Maybe SourceDependency
_ VersionConstraint
c) = VersionConstraint -> FilePath
renderVersionConstraint VersionConstraint
c
renderVersionConstraint :: VersionConstraint -> String
renderVersionConstraint :: VersionConstraint -> FilePath
renderVersionConstraint VersionConstraint
version = case VersionConstraint
version of
VersionConstraint
AnyVersion -> FilePath
""
VersionRange FilePath
x -> FilePath
" " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
x
renderBuildTools :: Map BuildTool DependencyVersion -> SystemBuildTools -> [Element]
renderBuildTools :: Map BuildTool DependencyVersion -> SystemBuildTools -> [Element]
renderBuildTools (((BuildTool, DependencyVersion) -> RenderBuildTool)
-> [(BuildTool, DependencyVersion)] -> [RenderBuildTool]
forall a b. (a -> b) -> [a] -> [b]
map (BuildTool, DependencyVersion) -> RenderBuildTool
renderBuildTool ([(BuildTool, DependencyVersion)] -> [RenderBuildTool])
-> (Map BuildTool DependencyVersion
-> [(BuildTool, DependencyVersion)])
-> Map BuildTool DependencyVersion
-> [RenderBuildTool]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map BuildTool DependencyVersion -> [(BuildTool, DependencyVersion)]
forall k a. Map k a -> [(k, a)]
Map.toList -> [RenderBuildTool]
xs) SystemBuildTools
systemBuildTools = [
FilePath -> Value -> Element
Field FilePath
"build-tools" ([FilePath] -> Value
CommaSeparatedList ([FilePath] -> Value) -> [FilePath] -> Value
forall a b. (a -> b) -> a -> b
$ [FilePath
x | BuildTools FilePath
x <- [RenderBuildTool]
xs] [FilePath] -> [FilePath] -> [FilePath]
forall a. [a] -> [a] -> [a]
++ SystemBuildTools -> [FilePath]
renderSystemBuildTools SystemBuildTools
systemBuildTools)
, FilePath -> Value -> Element
Field FilePath
"build-tool-depends" ([FilePath] -> Value
CommaSeparatedList [FilePath
x | BuildToolDepends FilePath
x <- [RenderBuildTool]
xs])
]
data RenderBuildTool = BuildTools String | BuildToolDepends String
renderBuildTool :: (BuildTool, DependencyVersion) -> RenderBuildTool
renderBuildTool :: (BuildTool, DependencyVersion) -> RenderBuildTool
renderBuildTool (BuildTool
buildTool, DependencyVersion -> FilePath
renderVersion -> FilePath
version) = case BuildTool
buildTool of
LocalBuildTool FilePath
executable -> FilePath -> RenderBuildTool
BuildTools (FilePath
executable FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
version)
BuildTool FilePath
pkg FilePath
executable
| FilePath
pkg FilePath -> FilePath -> Bool
forall a. Eq a => a -> a -> Bool
== FilePath
executable Bool -> Bool -> Bool
&& FilePath
executable FilePath -> [FilePath] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`elem` [FilePath]
knownBuildTools -> FilePath -> RenderBuildTool
BuildTools (FilePath
executable FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
version)
| Bool
otherwise -> FilePath -> RenderBuildTool
BuildToolDepends (FilePath
pkg FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
":" FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
executable FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
version)
where
knownBuildTools :: [String]
knownBuildTools :: [FilePath]
knownBuildTools = [
FilePath
"alex"
, FilePath
"c2hs"
, FilePath
"cpphs"
, FilePath
"greencard"
, FilePath
"haddock"
, FilePath
"happy"
, FilePath
"hsc2hs"
, FilePath
"hscolour"
]
renderSystemBuildTools :: SystemBuildTools -> [String]
renderSystemBuildTools :: SystemBuildTools -> [FilePath]
renderSystemBuildTools = ((FilePath, VersionConstraint) -> FilePath)
-> [(FilePath, VersionConstraint)] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map (FilePath, VersionConstraint) -> FilePath
renderSystemBuildTool ([(FilePath, VersionConstraint)] -> [FilePath])
-> (SystemBuildTools -> [(FilePath, VersionConstraint)])
-> SystemBuildTools
-> [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Map FilePath VersionConstraint -> [(FilePath, VersionConstraint)]
forall k a. Map k a -> [(k, a)]
Map.toList (Map FilePath VersionConstraint -> [(FilePath, VersionConstraint)])
-> (SystemBuildTools -> Map FilePath VersionConstraint)
-> SystemBuildTools
-> [(FilePath, VersionConstraint)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SystemBuildTools -> Map FilePath VersionConstraint
unSystemBuildTools
renderSystemBuildTool :: (String, VersionConstraint) -> String
renderSystemBuildTool :: (FilePath, VersionConstraint) -> FilePath
renderSystemBuildTool (FilePath
name, VersionConstraint
constraint) = FilePath
name FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ VersionConstraint -> FilePath
renderVersionConstraint VersionConstraint
constraint
renderGhcOptions :: [GhcOption] -> Element
renderGhcOptions :: [FilePath] -> Element
renderGhcOptions = FilePath -> Value -> Element
Field FilePath
"ghc-options" (Value -> Element)
-> ([FilePath] -> Value) -> [FilePath] -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> Value
WordList
renderGhcProfOptions :: [GhcProfOption] -> Element
renderGhcProfOptions :: [FilePath] -> Element
renderGhcProfOptions = FilePath -> Value -> Element
Field FilePath
"ghc-prof-options" (Value -> Element)
-> ([FilePath] -> Value) -> [FilePath] -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> Value
WordList
renderGhcjsOptions :: [GhcjsOption] -> Element
renderGhcjsOptions :: [FilePath] -> Element
renderGhcjsOptions = FilePath -> Value -> Element
Field FilePath
"ghcjs-options" (Value -> Element)
-> ([FilePath] -> Value) -> [FilePath] -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> Value
WordList
renderCppOptions :: [CppOption] -> Element
renderCppOptions :: [FilePath] -> Element
renderCppOptions = FilePath -> Value -> Element
Field FilePath
"cpp-options" (Value -> Element)
-> ([FilePath] -> Value) -> [FilePath] -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> Value
WordList
renderCcOptions :: [CcOption] -> Element
renderCcOptions :: [FilePath] -> Element
renderCcOptions = FilePath -> Value -> Element
Field FilePath
"cc-options" (Value -> Element)
-> ([FilePath] -> Value) -> [FilePath] -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> Value
WordList
renderCxxOptions :: [CxxOption] -> Element
renderCxxOptions :: [FilePath] -> Element
renderCxxOptions = FilePath -> Value -> Element
Field FilePath
"cxx-options" (Value -> Element)
-> ([FilePath] -> Value) -> [FilePath] -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> Value
WordList
renderLdOptions :: [LdOption] -> Element
renderLdOptions :: [FilePath] -> Element
renderLdOptions = FilePath -> Value -> Element
Field FilePath
"ld-options" (Value -> Element)
-> ([FilePath] -> Value) -> [FilePath] -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> Value
WordList
renderBuildable :: Bool -> Element
renderBuildable :: Bool -> Element
renderBuildable = FilePath -> Value -> Element
Field FilePath
"buildable" (Value -> Element) -> (Bool -> Value) -> Bool -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> Value
Literal (FilePath -> Value) -> (Bool -> FilePath) -> Bool -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bool -> FilePath
forall a. Show a => a -> FilePath
show
renderDefaultExtensions :: [String] -> Element
renderDefaultExtensions :: [FilePath] -> Element
renderDefaultExtensions = FilePath -> Value -> Element
Field FilePath
"default-extensions" (Value -> Element)
-> ([FilePath] -> Value) -> [FilePath] -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> Value
LineSeparatedList
renderOtherExtensions :: [String] -> Element
renderOtherExtensions :: [FilePath] -> Element
renderOtherExtensions = FilePath -> Value -> Element
Field FilePath
"other-extensions" (Value -> Element)
-> ([FilePath] -> Value) -> [FilePath] -> Element
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [FilePath] -> Value
LineSeparatedList
renderPaths :: [Path] -> Value
renderPaths :: [Path] -> Value
renderPaths = [FilePath] -> Value
LineSeparatedList ([FilePath] -> Value) -> ([Path] -> [FilePath]) -> [Path] -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Path -> FilePath) -> [Path] -> [FilePath]
forall a b. (a -> b) -> [a] -> [b]
map Path -> FilePath
renderPath
where
renderPath :: Path -> FilePath
renderPath :: Path -> FilePath
renderPath (Path FilePath
path)
| FilePath -> Bool
needsQuoting FilePath
path = FilePath -> FilePath
forall a. Show a => a -> FilePath
show FilePath
path
| Bool
otherwise = FilePath
path
needsQuoting :: FilePath -> Bool
needsQuoting :: FilePath -> Bool
needsQuoting = (Char -> Bool) -> FilePath -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (\Char
x -> Char -> Bool
isSpace Char
x Bool -> Bool -> Bool
|| Char
x Char -> Char -> Bool
forall a. Eq a => a -> a -> Bool
== Char
',')