Display conditionals correctly

This commit is contained in:
Andrea Bedini 2023-05-26 21:38:46 +08:00
parent e51484454e
commit 56f8b81838
6 changed files with 229 additions and 213 deletions

View File

@ -3,8 +3,10 @@
{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE ImportQualifiedPost #-} {-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE InstanceSigs #-} {-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE LambdaCase #-}
{-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE UndecidableInstances #-} {-# LANGUAGE UndecidableInstances #-}
{-# OPTIONS_GHC -Wno-orphans #-} {-# OPTIONS_GHC -Wno-orphans #-}
@ -13,8 +15,11 @@ module Distribution.Aeson where
import Data.Aeson import Data.Aeson
import Data.Aeson.Key qualified as Key import Data.Aeson.Key qualified as Key
import Data.Aeson.KeyMap qualified as KeyMap
import Data.Aeson.Types import Data.Aeson.Types
import Data.List (foldl1')
import Data.List.NonEmpty qualified as NE import Data.List.NonEmpty qualified as NE
import Data.Vector qualified as V
import Distribution.CabalSpecVersion import Distribution.CabalSpecVersion
import Distribution.Compat.Lens hiding ((.=)) import Distribution.Compat.Lens hiding ((.=))
import Distribution.Compat.Newtype import Distribution.Compat.Newtype
@ -25,7 +30,6 @@ import Distribution.ModuleName hiding (fromString)
import Distribution.PackageDescription import Distribution.PackageDescription
import Distribution.PackageDescription.FieldGrammar import Distribution.PackageDescription.FieldGrammar
import Distribution.Pretty import Distribution.Pretty
import Distribution.System
import Distribution.Types.Version import Distribution.Types.Version
import Distribution.Types.VersionRange import Distribution.Types.VersionRange
import Distribution.Utils.Generic (fromUTF8BS) import Distribution.Utils.Generic (fromUTF8BS)
@ -33,166 +37,97 @@ import Distribution.Utils.Path
import Distribution.Utils.ShortText qualified as ST import Distribution.Utils.ShortText qualified as ST
import Language.Haskell.Extension import Language.Haskell.Extension
newtype ViaPretty a = ViaPretty a -- Note: this JSONFieldGrammar is not quite general purpose.
--
instance Pretty a => ToJSON (ViaPretty a) where -- To help with the rendering of conditional dependencies, here we "push"
toJSON (ViaPretty a) = toJSON $ prettyShow a -- all the conditionals down.
-- So while the build-dependencies in a GenericPackageDescription could
newtype ViaUnpack a = ViaUnpack a -- be represented as:
--
instance (ToJSON o, Newtype o n) => ToJSON (ViaUnpack n) where -- {
toJSON (ViaUnpack n) = toJSON $ unpack n -- "build-depends": ["a", "b", "c"],
-- "conditionals": [{
deriving via String instance ToJSON Token -- "if": {"os": "darwin"},
-- "then": {
deriving via String instance ToJSON Token' -- "build-depends": ["d"]
-- }
deriving via String instance ToJSON FilePathNT -- }]
-- }
deriving via String instance ToJSON CompatFilePath --
-- we decide to represent them as
deriving via ViaUnpack CompatLicenseFile instance ToJSON CompatLicenseFile --
-- {
deriving via (ViaPretty VersionRange) instance ToJSON VersionRange -- "build-depends": [
-- "a",
deriving via ViaUnpack TestedWith instance ToJSON TestedWith -- "b",
-- "c",
deriving via (ViaPretty CompilerFlavor) instance ToJSON CompilerFlavor -- { "if": "os(darwin)", "then": "d" }
-- ]
deriving via (ViaPretty SpecVersion) instance ToJSON SpecVersion -- }
--
deriving via (ViaPretty SpecLicense) instance ToJSON SpecLicense -- Note: we also pretty-print the condition.
deriving via (ViaUnpack (List sep b a)) instance ToJSON a => ToJSON (List sep b a)
deriving via (ViaPretty (SymbolicPath from to)) instance ToJSON (SymbolicPath from to)
deriving via (ViaPretty BuildType) instance ToJSON BuildType
deriving via (ViaPretty PackageName) instance ToJSON PackageName
deriving via (ViaPretty Version) instance ToJSON Version
instance ToJSON RepoType
instance ToJSON KnownRepoType
deriving via (ViaPretty Extension) instance ToJSON Extension
deriving via (ViaPretty Language) instance ToJSON Language
deriving via (ViaUnpack (MQuoted a)) instance ToJSON a => ToJSON (MQuoted a)
deriving via (ViaPretty Dependency) instance ToJSON Dependency
deriving via (ViaPretty BenchmarkType) instance ToJSON BenchmarkType
deriving via (ViaPretty ForeignLibType) instance ToJSON ForeignLibType
deriving via (ViaPretty TestType) instance ToJSON TestType
deriving via (ViaPretty ExecutableScope) instance ToJSON ExecutableScope
deriving via (ViaPretty ForeignLibOption) instance ToJSON ForeignLibOption
deriving via (ViaPretty LibVersionInfo) instance ToJSON LibVersionInfo
deriving via (ViaPretty ModuleName) instance ToJSON ModuleName
deriving via (ViaPretty ModuleReexport) instance ToJSON ModuleReexport
deriving via (ViaPretty Mixin) instance ToJSON Mixin
deriving via (ViaPretty PkgconfigDependency) instance ToJSON PkgconfigDependency
deriving via (ViaPretty ExeDependency) instance ToJSON ExeDependency
deriving via (ViaPretty LegacyExeDependency) instance ToJSON LegacyExeDependency
deriving via (ViaPretty LibraryVisibility) instance ToJSON LibraryVisibility
deriving via (ViaPretty FlagName) instance ToJSON FlagName
deriving via (ViaPretty Arch) instance ToJSON Arch
deriving via (ViaPretty OS) instance ToJSON OS
instance ToJSON ConfVar where
toJSON (OS os) = object ["os" .= os]
toJSON (Arch arch) = object ["arcg" .= arch]
toJSON (PackageFlag flag) = object ["os" .= flag]
toJSON (Impl compiler version)
| isAnyVersion version = object ["compiler" .= compiler]
| otherwise = object ["compiler" .= compiler, "version" .= version]
instance ToJSON c => ToJSON (Condition c) where
toJSON (Var v) = toJSON v
toJSON (Lit b) = toJSON b
toJSON (CNot c) = object ["not" .= c]
toJSON (COr l r) = object ["or" .= [l, r]]
toJSON (CAnd l r) = object ["and" .= [l, r]]
newtype JSONFieldGrammar s a = JsonFG newtype JSONFieldGrammar s a = JsonFG
{ fieldGrammarJSON :: CabalSpecVersion -> s -> [Pair] { runJSONFieldGrammar :: CabalSpecVersion -> [Condition ConfVar] -> s -> [Pair]
} }
deriving (Functor) deriving (Functor)
type JSONFieldGrammar' s = JSONFieldGrammar s s type JSONFieldGrammar' s = JSONFieldGrammar s s
jsonFieldGrammar :: CabalSpecVersion -> JSONFieldGrammar s a -> s -> [Pair] jsonFieldGrammar :: CabalSpecVersion -> [Condition ConfVar] -> JSONFieldGrammar s a -> s -> [Pair]
jsonFieldGrammar v fg = fieldGrammarJSON fg v jsonFieldGrammar v cs fg = runJSONFieldGrammar fg v cs
instance Applicative (JSONFieldGrammar s) where instance Applicative (JSONFieldGrammar s) where
pure _ = JsonFG (\_ _ -> mempty) pure _ = JsonFG (\_ _ _ -> mempty)
JsonFG f <*> JsonFG x = JsonFG (\v s -> f v s <> x v s) JsonFG f <*> JsonFG x = JsonFG (\v cs s -> f v cs s <> x v cs s)
instance FieldGrammar ToJSON JSONFieldGrammar where instance FieldGrammar ToJSON JSONFieldGrammar where
blurFieldGrammar :: ALens' a b -> JSONFieldGrammar b d -> JSONFieldGrammar a d blurFieldGrammar :: ALens' a b -> JSONFieldGrammar b d -> JSONFieldGrammar a d
blurFieldGrammar f (JsonFG fg) = JsonFG $ \v -> blurFieldGrammar f (JsonFG fg) = JsonFG $ \v cs ->
fg v . aview f fg v cs . aview f
uniqueFieldAla :: (ToJSON b, Newtype a b) => FieldName -> (a -> b) -> ALens' s a -> JSONFieldGrammar s a uniqueFieldAla :: (ToJSON b, Newtype a b) => FieldName -> (a -> b) -> ALens' s a -> JSONFieldGrammar s a
uniqueFieldAla fn _pack l = JsonFG $ \_v -> uniqueFieldAla fn _pack l = JsonFG $ \_v cs ->
jsonField fn . toJSON . pack' _pack . aview l jsonField cs fn . toJSON . pack' _pack . aview l
booleanFieldDef :: FieldName -> ALens' s Bool -> Bool -> JSONFieldGrammar s Bool booleanFieldDef :: FieldName -> ALens' s Bool -> Bool -> JSONFieldGrammar s Bool
booleanFieldDef fn l def = JsonFG $ \_v s -> booleanFieldDef fn l def = JsonFG $ \_v cs s ->
let b = aview l s let b = aview l s
in if b == def in if b == def
then mempty then mempty
else jsonField fn (toJSON b) else jsonField cs fn (toJSON b)
optionalFieldAla :: (ToJSON b, Newtype a b) => FieldName -> (a -> b) -> ALens' s (Maybe a) -> JSONFieldGrammar s (Maybe a) optionalFieldAla :: (ToJSON b, Newtype a b) => FieldName -> (a -> b) -> ALens' s (Maybe a) -> JSONFieldGrammar s (Maybe a)
optionalFieldAla fn _pack l = JsonFG $ \_ s -> optionalFieldAla fn _pack l = JsonFG $ \_ cs s ->
case aview l s of case aview l s of
Nothing -> mempty Nothing -> mempty
Just a -> jsonField fn (toJSON (pack' _pack a)) Just a -> jsonField cs fn (toJSON (pack' _pack a))
optionalFieldDefAla :: (ToJSON b, Newtype a b, Eq a) => FieldName -> (a -> b) -> ALens' s a -> a -> JSONFieldGrammar s a optionalFieldDefAla :: (ToJSON b, Newtype a b, Eq a) => FieldName -> (a -> b) -> ALens' s a -> a -> JSONFieldGrammar s a
optionalFieldDefAla fn _pack l def = JsonFG $ \_ s -> optionalFieldDefAla fn _pack l def = JsonFG $ \_ cs s ->
let x = aview l s let x = aview l s
in if x == def in if x == def
then mempty then mempty
else jsonField fn (toJSON (pack' _pack x)) else jsonField cs fn (toJSON (pack' _pack x))
freeTextField :: FieldName -> ALens' s (Maybe String) -> JSONFieldGrammar s (Maybe String) freeTextField :: FieldName -> ALens' s (Maybe String) -> JSONFieldGrammar s (Maybe String)
freeTextField fn l = JsonFG $ \_v s -> freeTextField fn l = JsonFG $ \_v cs s ->
maybe mempty (jsonField fn . toJSON) (aview l s) maybe mempty (jsonField cs fn . toJSON) (aview l s)
freeTextFieldDef :: FieldName -> ALens' s String -> JSONFieldGrammar s String freeTextFieldDef :: FieldName -> ALens' s String -> JSONFieldGrammar s String
freeTextFieldDef fn l = JsonFG $ \_v -> freeTextFieldDef fn l = JsonFG $ \_v cs ->
jsonField fn . toJSON . aview l jsonField cs fn . toJSON . aview l
freeTextFieldDefST :: FieldName -> ALens' s ST.ShortText -> JSONFieldGrammar s ST.ShortText freeTextFieldDefST :: FieldName -> ALens' s ST.ShortText -> JSONFieldGrammar s ST.ShortText
freeTextFieldDefST = defaultFreeTextFieldDefST freeTextFieldDefST = defaultFreeTextFieldDefST
monoidalFieldAla :: (ToJSON b, Monoid a, Newtype a b) => FieldName -> (a -> b) -> ALens' s a -> JSONFieldGrammar s a monoidalFieldAla :: (ToJSON b, Monoid a, Newtype a b) => FieldName -> (a -> b) -> ALens' s a -> JSONFieldGrammar s a
monoidalFieldAla fn _pack l = JsonFG $ \_v -> monoidalFieldAla fn _pack l = JsonFG $ \_v cs ->
jsonField fn . toJSON . pack' _pack . aview l jsonField cs fn . toJSON . pack' _pack . aview l
prefixedFields :: FieldName -> ALens' s [(String, String)] -> JSONFieldGrammar s [(String, String)] prefixedFields :: FieldName -> ALens' s [(String, String)] -> JSONFieldGrammar s [(String, String)]
prefixedFields fnPfx l = JsonFG $ \_v s -> prefixedFields _fnPfx l = JsonFG $ \_v _cs s ->
[Key.fromString (fromUTF8BS fnPfx <> n) .= v | (n, v) <- aview l s] [Key.fromString n .= v | (n, v) <- aview l s]
knownField :: FieldName -> JSONFieldGrammar s () knownField :: FieldName -> JSONFieldGrammar s ()
knownField _ = pure () knownField _ = pure ()
@ -209,21 +144,30 @@ instance FieldGrammar ToJSON JSONFieldGrammar where
hiddenField _ = JsonFG (const mempty) hiddenField _ = JsonFG (const mempty)
jsonField :: FieldName -> Value -> [Pair] jsonField :: [Condition ConfVar] -> FieldName -> Value -> [Pair]
jsonField fn v jsonField cs fn v
| v == emptyArray = mempty | v == emptyArray = mempty
| v == emptyString = mempty | v == emptyString = mempty
| otherwise = [Key.fromString (fromUTF8BS fn) .= v] | null cs = [Key.fromString (fromUTF8BS fn) .= v]
| otherwise = [Key.fromString (fromUTF8BS fn) .= v']
where where
v' = object ["if" .= showCondition (foldl1' cAnd cs), "then" .= v]
-- Should be added to aeson -- Should be added to aeson
emptyString :: Value emptyString :: Value
emptyString = String "" emptyString = String ""
jsonGenericPackageDescription :: GenericPackageDescription -> Value jsonGenericPackageDescription :: GenericPackageDescription -> Value
jsonGenericPackageDescription gpd = jsonGenericPackageDescription gpd = jsonGenericPackageDescription' v gpd
where
v = specVersion $ packageDescription gpd
jsonGenericPackageDescription' :: CabalSpecVersion -> GenericPackageDescription -> Value
jsonGenericPackageDescription' v gpd =
object $ object $
concat concat
[ jsonPackageDescription v (packageDescription gpd), [ jsonPackageDescription v (packageDescription gpd),
jsonSetupBuildInfo v (setupBuildInfo (packageDescription gpd)),
jsonGenPackageFlags v (genPackageFlags gpd), jsonGenPackageFlags v (genPackageFlags gpd),
jsonCondLibrary v (condLibrary gpd), jsonCondLibrary v (condLibrary gpd),
jsonCondSubLibraries v (condSubLibraries gpd), jsonCondSubLibraries v (condSubLibraries gpd),
@ -232,12 +176,10 @@ jsonGenericPackageDescription gpd =
jsonCondTestSuites v (condTestSuites gpd), jsonCondTestSuites v (condTestSuites gpd),
jsonCondBenchmarks v (condBenchmarks gpd) jsonCondBenchmarks v (condBenchmarks gpd)
] ]
where
v = specVersion $ packageDescription gpd
jsonPackageDescription :: CabalSpecVersion -> PackageDescription -> [Pair] jsonPackageDescription :: CabalSpecVersion -> PackageDescription -> [Pair]
jsonPackageDescription v pd@PackageDescription {sourceRepos, setupBuildInfo} = jsonPackageDescription v pd@PackageDescription {sourceRepos, setupBuildInfo} =
jsonFieldGrammar v packageDescriptionFieldGrammar pd jsonFieldGrammar v [] packageDescriptionFieldGrammar pd
<> jsonSourceRepos v sourceRepos <> jsonSourceRepos v sourceRepos
<> jsonSetupBuildInfo v setupBuildInfo <> jsonSetupBuildInfo v setupBuildInfo
@ -245,21 +187,21 @@ jsonSourceRepos :: CabalSpecVersion -> [SourceRepo] -> [Pair]
jsonSourceRepos v = jsonSourceRepos v =
concatMap (\neRepos -> ["source-repository" .= NE.map (jsonSourceRepo v) neRepos]) . NE.nonEmpty concatMap (\neRepos -> ["source-repository" .= NE.map (jsonSourceRepo v) neRepos]) . NE.nonEmpty
jsonSetupBuildInfo :: CabalSpecVersion -> Maybe SetupBuildInfo -> [Pair]
jsonSetupBuildInfo v =
concatMap (\sbi -> ["custom-setup" .= jsonFieldGrammar v (setupBInfoFieldGrammar False) sbi])
jsonSourceRepo :: CabalSpecVersion -> SourceRepo -> Value jsonSourceRepo :: CabalSpecVersion -> SourceRepo -> Value
jsonSourceRepo v repo@SourceRepo {repoKind} = jsonSourceRepo v repo@SourceRepo {repoKind} =
object $ jsonFieldGrammar v (sourceRepoFieldGrammar repoKind) repo object $ jsonFieldGrammar v [] (sourceRepoFieldGrammar repoKind) repo
jsonSetupBuildInfo :: CabalSpecVersion -> Maybe SetupBuildInfo -> [Pair]
jsonSetupBuildInfo v =
concatMap (\sbi -> ["custom-setup" .= jsonFieldGrammar v [] (setupBInfoFieldGrammar False) sbi])
jsonGenPackageFlags :: CabalSpecVersion -> [PackageFlag] -> [Pair] jsonGenPackageFlags :: CabalSpecVersion -> [PackageFlag] -> [Pair]
jsonGenPackageFlags v = jsonGenPackageFlags v =
concatMap (\neFlags -> ["flags" .= NE.map (jsonFlag v) neFlags]) . NE.nonEmpty concatMap (\neFlags -> ["flags" .= object (NE.toList $ NE.map (jsonFlag v) neFlags)]) . NE.nonEmpty
jsonFlag :: CabalSpecVersion -> PackageFlag -> Value jsonFlag :: CabalSpecVersion -> PackageFlag -> Pair
jsonFlag v flag@(MkPackageFlag name _ _ _) = jsonFlag v flag@(MkPackageFlag name _ _ _) =
object [Key.fromString (unFlagName name) .= jsonFieldGrammar v (flagFieldGrammar name) flag] Key.fromString (unFlagName name) .= object (jsonFieldGrammar v [] (flagFieldGrammar name) flag)
jsonCondLibrary :: CabalSpecVersion -> Maybe (CondTree ConfVar [Dependency] Library) -> [Pair] jsonCondLibrary :: CabalSpecVersion -> Maybe (CondTree ConfVar [Dependency] Library) -> [Pair]
jsonCondLibrary v = jsonCondLibrary v =
@ -310,27 +252,117 @@ jsonCondBenchmark v (n, condTree) =
withName (unUnqualComponentName n) $ withName (unUnqualComponentName n) $
jsonCondTree v benchmarkFieldGrammar (fmap unvalidateBenchmark condTree) jsonCondTree v benchmarkFieldGrammar (fmap unvalidateBenchmark condTree)
jsonCondTree :: CabalSpecVersion -> JSONFieldGrammar' s -> CondTree ConfVar [Dependency] s -> [Pair] jsonCondTree :: forall s. CabalSpecVersion -> JSONFieldGrammar' s -> CondTree ConfVar [Dependency] s -> [Pair]
jsonCondTree v grammar = goNode jsonCondTree v grammar = go []
where where
goNode (CondNode it _ ifs) = go cs (CondNode it _ ifs) =
jsonFieldGrammar v grammar it ++ concatMap goBranch ifs KeyMap.toList $ foldr merge (KeyMap.fromList $ jsonFieldGrammar v cs grammar it) $ concatMap (jsonIf cs) ifs
goBranch (CondBranch c ifTrue Nothing) = jsonIf :: [Condition ConfVar] -> CondBranch ConfVar c s -> [Pair]
[ "if" jsonIf cs (CondBranch c thenTree Nothing) =
.= object go (c : cs) thenTree
[ "cond" .= c, jsonIf cs (CondBranch c thenTree (Just elseTree)) =
"then" .= object (jsonCondTree v grammar ifTrue) go (c : cs) thenTree ++ go (cNot c : cs) elseTree
]
]
goBranch (CondBranch c ifTrue (Just ifFalse)) =
[ "if"
.= object
[ "cond" .= c,
"then" .= object (jsonCondTree v grammar ifTrue),
"else" .= object (jsonCondTree v grammar ifFalse)
]
]
withName :: ToJSON v => v -> [Pair] -> Value merge :: Pair -> KeyMap.KeyMap Value -> KeyMap.KeyMap Value
merge = uncurry $ KeyMap.insertWith $ \new ->
\case
(Array a) -> Array (a `V.snoc` new)
old -> Array (V.fromList [old, new])
withName :: (ToJSON v) => v -> [Pair] -> Value
withName n s = object $ ("name" .= n) : s withName n s = object $ ("name" .= n) : s
showCondition :: Condition ConfVar -> String
showCondition (Var x) = showConfVar x
showCondition (Lit b) = show b
showCondition (CNot c) = "!" <> showCondition c
showCondition (COr c1 c2) = "(" <> unwords [showCondition c1, "||", showCondition c2] <> ")"
showCondition (CAnd c1 c2) = "(" <> unwords [showCondition c1, "&&", showCondition c2] <> ")"
showConfVar :: ConfVar -> String
showConfVar (OS os) = "os(" <> prettyShow os <> ")"
showConfVar (Arch arch) = "arch(" <> prettyShow arch <> ")"
showConfVar (PackageFlag name) = "flag(" <> unFlagName name <> ")"
showConfVar (Impl c v) = "impl(" <> prettyShow c <> " " <> prettyShow v <> ")"
showIfCondition :: Condition ConfVar -> String
showIfCondition c = "if " <> showCondition c
newtype ViaPretty a = ViaPretty a
instance (Pretty a) => ToJSON (ViaPretty a) where
toJSON (ViaPretty a) = toJSON $ prettyShow a
newtype ViaUnpack a = ViaUnpack a
instance (ToJSON o, Newtype o n) => ToJSON (ViaUnpack n) where
toJSON (ViaUnpack n) = toJSON $ unpack n
deriving via String instance ToJSON Token
deriving via String instance ToJSON Token'
deriving via String instance ToJSON FilePathNT
deriving via String instance ToJSON CompatFilePath
deriving via ViaUnpack CompatLicenseFile instance ToJSON CompatLicenseFile
deriving via (ViaPretty VersionRange) instance ToJSON VersionRange
deriving via ViaUnpack TestedWith instance ToJSON TestedWith
deriving via (ViaPretty CompilerFlavor) instance ToJSON CompilerFlavor
deriving via (ViaPretty SpecVersion) instance ToJSON SpecVersion
deriving via (ViaPretty SpecLicense) instance ToJSON SpecLicense
deriving via (ViaUnpack (List sep b a)) instance (ToJSON a) => ToJSON (List sep b a)
deriving via (ViaPretty (SymbolicPath from to)) instance ToJSON (SymbolicPath from to)
deriving via (ViaPretty BuildType) instance ToJSON BuildType
deriving via (ViaPretty PackageName) instance ToJSON PackageName
deriving via (ViaPretty Version) instance ToJSON Version
instance ToJSON RepoType
instance ToJSON KnownRepoType
deriving via (ViaPretty Extension) instance ToJSON Extension
deriving via (ViaPretty Language) instance ToJSON Language
deriving via (ViaUnpack (MQuoted a)) instance (ToJSON a) => ToJSON (MQuoted a)
deriving via (ViaPretty Dependency) instance ToJSON Dependency
deriving via (ViaPretty BenchmarkType) instance ToJSON BenchmarkType
deriving via (ViaPretty ForeignLibType) instance ToJSON ForeignLibType
deriving via (ViaPretty TestType) instance ToJSON TestType
deriving via (ViaPretty ExecutableScope) instance ToJSON ExecutableScope
deriving via (ViaPretty ForeignLibOption) instance ToJSON ForeignLibOption
deriving via (ViaPretty LibVersionInfo) instance ToJSON LibVersionInfo
deriving via (ViaPretty ModuleName) instance ToJSON ModuleName
deriving via (ViaPretty ModuleReexport) instance ToJSON ModuleReexport
deriving via (ViaPretty Mixin) instance ToJSON Mixin
deriving via (ViaPretty PkgconfigDependency) instance ToJSON PkgconfigDependency
deriving via (ViaPretty ExeDependency) instance ToJSON ExeDependency
deriving via (ViaPretty LegacyExeDependency) instance ToJSON LegacyExeDependency
deriving via (ViaPretty LibraryVisibility) instance ToJSON LibraryVisibility

View File

@ -14,7 +14,6 @@ module Foliage.Pages
) )
where where
import Control.Monad (unless)
import Data.Aeson (KeyValue ((.=)), ToJSON, object) import Data.Aeson (KeyValue ((.=)), ToJSON, object)
import Data.Function (on, (&)) import Data.Function (on, (&))
import Data.List (sortOn) import Data.List (sortOn)
@ -24,7 +23,7 @@ import Data.Ord (Down (Down), comparing)
import Data.Text.Lazy.IO.Utf8 qualified as TL import Data.Text.Lazy.IO.Utf8 qualified as TL
import Data.Time (UTCTime) import Data.Time (UTCTime)
import Data.Time.Clock.POSIX (POSIXTime, utcTimeToPOSIXSeconds) import Data.Time.Clock.POSIX (POSIXTime, utcTimeToPOSIXSeconds)
import Development.Shake (Action, putWarn, traced) import Development.Shake (Action, traced)
import Distribution.Aeson (jsonGenericPackageDescription) import Distribution.Aeson (jsonGenericPackageDescription)
import Distribution.Package (PackageIdentifier (pkgName, pkgVersion)) import Distribution.Package (PackageIdentifier (pkgName, pkgVersion))
import Distribution.Pretty (prettyShow) import Distribution.Pretty (prettyShow)
@ -35,7 +34,7 @@ import Foliage.Utils.Aeson (MyAesonEncoding (..))
import GHC.Generics (Generic) import GHC.Generics (Generic)
import System.Directory qualified as IO import System.Directory qualified as IO
import System.FilePath ((</>)) import System.FilePath ((</>))
import Text.Mustache (Template, displayMustacheWarning, renderMustacheW) import Text.Mustache (Template)
import Text.Mustache.Compile.TH (compileMustacheDir) import Text.Mustache.Compile.TH (compileMustacheDir)
import Text.Mustache.Render (renderMustache) import Text.Mustache.Render (renderMustache)
@ -144,29 +143,18 @@ makeAllPackageVersionsPage currentTime outputDir packageVersions =
& sortOn (Down . allPackageVersionsPageEntryTimestamp) & sortOn (Down . allPackageVersionsPageEntryTimestamp)
makePackageVersionPage :: FilePath -> PreparedPackageVersion -> Action () makePackageVersionPage :: FilePath -> PreparedPackageVersion -> Action ()
makePackageVersionPage makePackageVersionPage outputDir PreparedPackageVersion {pkgId, pkgTimestamp, pkgVersionSource, pkgDesc, cabalFileRevisions, pkgVersionIsDeprecated} = do
outputDir traced ("webpages / package / " ++ prettyShow pkgId) $ do
PreparedPackageVersion IO.createDirectoryIfMissing True (outputDir </> "package" </> prettyShow pkgId)
{ pkgId, TL.writeFile (outputDir </> "package" </> prettyShow pkgId </> "index.html") $
pkgTimestamp, renderMustache packageVersionPageTemplate $
pkgVersionSource, object
pkgDesc, [ "pkgVersionSource" .= pkgVersionSource,
cabalFileRevisions, "cabalFileRevisions" .= map fst cabalFileRevisions,
pkgVersionIsDeprecated "pkgDesc" .= jsonGenericPackageDescription pkgDesc,
} = do "pkgTimestamp" .= pkgTimestamp,
let (warnings, text) = "pkgVersionDeprecated" .= pkgVersionIsDeprecated
renderMustacheW packageVersionPageTemplate $ ]
object
[ "pkgVersionSource" .= pkgVersionSource,
"cabalFileRevisions" .= map fst cabalFileRevisions,
"pkgDesc" .= jsonGenericPackageDescription pkgDesc,
"pkgTimestamp" .= pkgTimestamp,
"pkgVersionDeprecated" .= pkgVersionIsDeprecated
]
traced ("webpages / package / " ++ prettyShow pkgId) $ do
IO.createDirectoryIfMissing True (outputDir </> "package" </> prettyShow pkgId)
TL.writeFile (outputDir </> "package" </> prettyShow pkgId </> "index.html") text
unless (null warnings) $ putWarn $ unlines (map displayMustacheWarning warnings)
indexPageTemplate :: Template indexPageTemplate :: Template
indexPageTemplate = $(compileMustacheDir "index" "templates") indexPageTemplate = $(compileMustacheDir "index" "templates")

View File

@ -65,5 +65,6 @@ executable foliage
time >=1.9.3 && <1.13, time >=1.9.3 && <1.13,
time-compat >=1.9.6.1 && <1.10, time-compat >=1.9.6.1 && <1.10,
tomland >=1.3.3.1 && <1.4, tomland >=1.3.3.1 && <1.4,
vector >=0.13.0.0 && <0.14,
with-utf8 >=1.0.2.3 && <1.1, with-utf8 >=1.0.2.3 && <1.1,
zlib >=0.6.2.3 && <0.7 zlib >=0.6.2.3 && <0.7,

View File

@ -1,9 +0,0 @@
{{#build-depends}}
<li>{{.}}</li>
{{/build-depends}}
{{#if.then.build-depends}}
<li>{{.}} if {{if.cond}}</li>
{{/if.then.build-depends}}
{{#if.else.build-depends}}
<li>{{.}} unless {{if.cond}}</li>
{{/if.else.build-depends}}

View File

@ -0,0 +1,17 @@
<ul class="build-depends">
{{#build-depends}}
{{^if}}
<li>{{.}}</li>
{{/if}}
{{/build-depends}}
</ul>
{{#build-depends}}
{{#if}}
<p>if {{.}}</p>
<ul class="build-depends">
{{#then}}
<li>{{.}}</li>
{{/then}}
</ul>
{{/if}}
{{/build-depends}}

View File

@ -13,7 +13,6 @@
</title> </title>
<style> <style>
ul.build-depends { ul.build-depends {
display: inline;
list-style: none; list-style: none;
} }
@ -93,51 +92,39 @@
<dd class="col-sm-9"> <dd class="col-sm-9">
<dl> <dl>
{{#pkgDesc.library}} {{#pkgDesc.library}}
<dt>library:</dt> <dt>library {{pkgDesc.name}}:</dt>
<dd> <dd>
<ul class="build-depends"> {{> dependencies}}
{{> cond-tree-dependency}}
</ul>
</dd> </dd>
{{/pkgDesc.library}} {{/pkgDesc.library}}
{{#pkgDesc.sub-libraries}} {{#pkgDesc.sub-libraries}}
<dt>library {{name}}:</dt> <dt>library {{name}}:</dt>
<dd> <dd>
<ul class="build-depends"> {{> dependencies}}
{{> cond-tree-dependency}}
</ul>
</dd> </dd>
{{/pkgDesc.sub-libraries}} {{/pkgDesc.sub-libraries}}
{{#pkgDesc.foreign-libraries}} {{#pkgDesc.foreign-libraries}}
<dt>foreign library {{name}}:</dt> <dt>foreign library {{name}}:</dt>
<dd> <dd>
<ul class="build-depends"> {{> dependencies}}
{{> cond-tree-dependency}}
</ul>
</dd> </dd>
{{/pkgDesc.foreign-libraries}} {{/pkgDesc.foreign-libraries}}
{{#pkgDesc.executables}} {{#pkgDesc.executables}}
<dt>executable {{name}}:</dt> <dt>executable {{name}}:</dt>
<dd> <dd>
<ul class="build-depends"> {{> dependencies}}
{{> cond-tree-dependency}}
</ul>
</dd> </dd>
{{/pkgDesc.executables}} {{/pkgDesc.executables}}
{{#pkgDesc.test-suites}} {{#pkgDesc.test-suites}}
<dt>test-suite {{name}}:</dt> <dt>test-suite {{name}}:</dt>
<dd> <dd>
<ul class="build-depends"> {{> dependencies}}
{{> cond-tree-dependency}}
</ul>
</dd> </dd>
{{/pkgDesc.test-suites}} {{/pkgDesc.test-suites}}
{{#pkgDesc.benchmarks}} {{#pkgDesc.benchmarks}}
<dt>benchmark {{name}}:</dt> <dt>benchmark {{name}}:</dt>
<dd> <dd>
<ul class="build-depends"> {{> dependencies}}
{{> cond-tree-dependency}}
</ul>
</dd> </dd>
{{/pkgDesc.benchmarks}} {{/pkgDesc.benchmarks}}
</dl> </dl>