{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE CPP #-}
module Hpack.Render (
-- | /__NOTE:__/ This module is exposed to allow integration of Hpack into
-- other tools.  It is not meant for general use by end users.  The following
-- caveats apply:
--
-- * The API is undocumented, consult the source instead.
--
-- * The exposed types and functions primarily serve Hpack's own needs, not
-- that of a public API.  Breaking changes can happen as Hpack evolves.
--
-- As an Hpack user you either want to use the @hpack@ executable or a build
-- tool that supports Hpack (e.g. @stack@ or @cabal2nix@).

  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
',')