-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | parser for config files, shell variables, command line args. -- @package configifier @version 0.0.5 module Data.Configifier -- | Construction of config records (cons for record fields). data (:*>) a b (:*>) :: a -> b -> (:*>) a b -- | Construction of config record fields. data (:>) (s :: Symbol) (t :: *) -- | Add descriptive text to record field for documentation. data (:>:) a (s :: Symbol) data ConfigCode k Record :: (ConfigCode k) -> (ConfigCode k) -> ConfigCode k Label :: Symbol -> (ConfigCode k) -> ConfigCode k Descr :: (ConfigCode k) -> Symbol -> ConfigCode k List :: (ConfigCode k) -> ConfigCode k Option :: (ConfigCode k) -> ConfigCode k Type :: k -> ConfigCode k -- | Map user-provided config type to ConfigCode types. -- | Deprecated: use of NoDesc is redundant and can be dropped without -- replacement. -- | Map ConfgCode types to the types of config values. -- | MaybeO is isomorphic to Maybe, but is only used for -- Option values. data MaybeO a JustO :: a -> MaybeO a NothingO :: MaybeO a -- | Transformers' Identity is not in Typeable, so we roll -- our own. It's also less work to write. data Id a Id :: a -> Id a data Source YamlString :: SBS -> Source YamlFile :: FilePath -> Source ShellEnv :: [(String, String)] -> Source CommandLine :: [String] -> Source data ConfigFile data ShellEnv data CommandLine data Tagged cfg Tagged :: ToConfig cfg Id -> Tagged cfg fromTagged :: Tagged cfg -> ToConfig cfg Id data TaggedM cfg TaggedM :: ToConfig cfg Maybe -> TaggedM cfg fromTaggedM :: TaggedM cfg -> ToConfig cfg Maybe data Error InvalidYamlString :: SBS -> ParseException -> Error invalidYamlInput :: Error -> SBS invalidYamlMsg :: Error -> ParseException InvalidYamlFile :: FilePath -> ParseException -> Error invalidYamlFile :: Error -> FilePath invalidYamlMsg :: Error -> ParseException ShellEnvNil :: Error ShellEnvNoParse :: String -> String -> String -> Error shellEnvNoParseType :: Error -> String shellEnvNoParseValue :: Error -> String shellEnvNoParseMsg :: Error -> String CommandLinePrimitiveParseError :: String -> Error CommandLinePrimitiveOtherError :: Error -> Error FreezeIncomplete :: [String] -> Error freezeIncompleteAtPath :: Error -> [String] configify :: (tm ~ TaggedM cfg, Show tm, Monoid tm, Freeze cfg, FromJSON tm, HasParseShellEnv cfg, HasParseCommandLine cfg, CanonicalizePartial cfg) => [Source] -> IO (Tagged cfg) configifyWithDefault :: (tm ~ TaggedM cfg, Show tm, Monoid tm, Freeze cfg, FromJSON tm, HasParseShellEnv cfg, HasParseCommandLine cfg, CanonicalizePartial cfg) => tm -> [Source] -> IO (Tagged cfg) -- | From a list of config file paths, construct a source list that (1) -- reads those files allowing for recursive includes; then (2) processes -- shell environment variables (with getProgName as prefix), and -- finally (3) processes command line args, turning --config -- arguments into further recursive config file loads. defaultSources :: [FilePath] -> IO [Source] -- | Require that all shell env variables start with executable name. (This -- is just a call to requireShellEnvPrefix' with the result of -- progName.) withShellEnvPrefix :: Env -> IO Env -- | Handle `--config=<FILE>`, `--config FILE`: split up -- CommandLine source on each of these, and inject a -- YamlFile source with the resp. file name. readUserConfigFiles :: [Source] -> [Source] -- | Require prefix for shell env variables. This function will chop off -- the given prefix of all env entries, and filter all entries that do -- not have this prefix. withShellEnvPrefix' :: String -> Env -> Env parseConfigFile :: FromJSON (TaggedM cfg) => SBS -> Either Error (TaggedM cfg) -- | See Data.Yaml.Include. parseConfigFileWithIncludes :: FromJSON (TaggedM cfg) => FilePath -> IO (Either Error (TaggedM cfg)) renderConfigFile :: (Freeze cfg, t ~ Tagged cfg, ToJSON (TaggedM cfg)) => t -> SBS -- |
-- instance ToJSON Record ---- |
-- instance ToJSON Label ---- |
-- instance ToJSON List ---- |
-- instance ToJSON Option ---- |
-- instance ToJSON Type ---- |
-- instance FromJSON Record ---- | instance FromJSON Label (tolerates unknown fields in json -- object.) -- |
-- instance ParseJSON List ---- |
-- instance ParseJSON Option ---- |
-- instance FromJSON Type --type Env = [(String, String)] class HasParseShellEnv (cfg :: ConfigCode *) parseShellEnv :: HasParseShellEnv cfg => Env -> Either Error (TaggedM cfg) -- | The paths into the recursive structure of the config file are -- concatenated to shell variable names with separating '_'. (It is still -- ok to have '_' in your config path names. This parser chops off -- complete matching names, whether they contain '_' or not, and only -- then worries about trailing '_'.) -- | You can provide a list value via the shell environment by providing a -- single element. This element will be put into a list implicitly. -- -- (A more general approach that allows for yaml-encoded list values in -- shell variables is more tricky to design, implement, and use: If you -- have a list of sub-configs and don't want the entire sub-config to be -- yaml-encoded, but use a longer shell variable name to go further down -- to deeper sub-configs, there is a lot of ambiguity. It may be possible -- to resolve that at run-time, but it's more tricky.) type Args = [String] class HasParseCommandLine cfg parseCommandLine :: HasParseCommandLine cfg => [String] -> Either Error (TaggedM cfg) -- | Very basic first approach: read --(key)(=|s+)(value); -- construct shell env from keys and names, and use parseShellEnv -- on the command line. If it doesn't like the syntax used in the command -- line, it will crash. I hope for this to get much fancier in the -- future. primitiveParseCommandLine :: HasParseShellEnv cfg => [String] -> Either Error (TaggedM cfg) parseArgs :: Args -> Either String Env popArg :: Args -> Either String ((String, String), Args) parseArgsWithEqSign :: String -> Either String (String, String) parseArgsWithSpace :: String -> String -> Either String (String, String) parseArgName :: String -> String -- | Map a Tagged config value and a type-level path to the part of -- the config value the path points to. Trigger an informative type error -- if path does not exist. (>>.) :: (Sel cfg ps, ToValE cfg ps ~ Done r) => Tagged cfg -> Proxy ps -> r -- | Map ConfgCode types to the types of config values. -- | This is <|> on Maybe lifted to the type level. -- | Compile-time Maybe. Type-level Just / Nothing (as -- produced by ToVal) are embedded in each constructor, resp.. -- Since Just and Nothing are different types, -- CNothing and CJust can be distinguished by the type -- checker. data CMaybe (a :: Maybe *) CNothing :: CMaybe Nothing CJust :: a -> CMaybe (Just a) -- | This is a version of <|> on Maybe for -- CMaybe. orElse :: CMaybe a -> CMaybe b -> CMaybe (OrElse a b) toValueMaybe :: CMaybe a -> CMaybe (ToValueMaybe a) class NothingValue (a :: Maybe *) nothingValue :: NothingValue a => Proxy a -> CMaybe (ToValueMaybe a) class Sel cfg ps sel :: Sel cfg ps => Tagged cfg -> Proxy ps -> CMaybe (ToVal cfg ps) -- | Helper class for disambiguating overlaps. The trick is that the -- Sel instance based on the Sel' constraint is more -- general than all other instances, so OverlappingInstances -- will ensure it is matched last. This way, no instance of Sel' -- can wrongly overlap with any instance of Sel. class Sel' cfg ps sel' :: Sel' cfg ps => Tagged cfg -> Proxy ps -> CMaybe (ToVal cfg ps) type ToValE (a :: ConfigCode *) (p :: [Symbol]) = ToExc (LookupFailed a p) (ToVal a p) data Exc a b Fail :: a -> Exc a b Done :: b -> Exc a b data LookupFailed a p merge :: (tm ~ TaggedM cfg, ti ~ Tagged cfg, Freeze cfg, Monoid tm, CanonicalizePartial cfg) => [tm] -> Either Error ti freeze :: (tm ~ TaggedM cfg, ti ~ Tagged cfg, Freeze cfg) => tm -> Either Error ti thaw :: (tm ~ TaggedM cfg, ti ~ Tagged cfg, Freeze cfg) => ti -> tm -- | If one of two configs is Nothing, do the expected thing. If -- both are Just, append the values. -- | There is no instance Monoid (TaggedM (Type a)), since there -- is no reasonable mempty. Therefore, we offer a specialized -- instance for labels that map to Type. -- | Lists are initialized empty by default. Append overwrites left values -- with right values. (If we tried to append list elements recursively, -- there would be awkward questions about matching list lengths.) class Freeze c frz :: Freeze c => Proxy c -> [String] -> ToConfig c Maybe -> Either Error (ToConfig c Id) thw :: Freeze c => Proxy c -> ToConfig c Id -> ToConfig c Maybe -- | FIXME: if a non-optional part of an optional sub-config is missing, -- the FreezeIncomplete error is ignored and the entire sub-config -- is cleared. it would be better to distinguish between the cases -- `sub-config missing` and `sub-config provided incompletely`, and still -- raise an error in the latter. -- | Partials are constructed with every Nothing spelled out, -- resulting in deep skeletons of Nothings. -- CanonicalizePartial replaces those with single Nothings -- at their tops. class CanonicalizePartial a canonicalizePartial :: CanonicalizePartial a => TaggedM a -> TaggedM a emptyPartial :: CanonicalizePartial a => TaggedM a -> Bool docs :: (HasToDoc a, HasRenderDoc ConfigFile, HasRenderDoc ShellEnv, HasRenderDoc CommandLine) => Proxy a -> ST data Doc DocDict :: [(String, Maybe String, Doc, DocOptional)] -> Doc DocList :: Doc -> Doc DocType :: String -> Doc data DocOptional DocMandatory :: DocOptional DocOptional :: DocOptional concatDoc :: Doc -> Doc -> Doc class HasToDoc (a :: ConfigCode *) toDoc :: HasToDoc a => Proxy a -> Doc class HasRenderDoc t renderDoc :: HasRenderDoc t => Proxy t -> Doc -> ST instance [overlap ok] Typeable (:*>) instance [overlap ok] Typeable (:>) instance [overlap ok] Typeable (:>:) instance [overlap ok] Typeable MaybeO instance [overlap ok] Typeable Id instance [overlap ok] Typeable Source instance [overlap ok] Typeable Error instance [overlap ok] Typeable DocOptional instance [overlap ok] Typeable Doc instance [overlap ok] (Eq a, Eq b) => Eq (a :*> b) instance [overlap ok] (Ord a, Ord b) => Ord (a :*> b) instance [overlap ok] (Show a, Show b) => Show (a :*> b) instance [overlap ok] Eq a => Eq (MaybeO a) instance [overlap ok] Ord a => Ord (MaybeO a) instance [overlap ok] Show a => Show (MaybeO a) instance [overlap ok] Eq a => Eq (Id a) instance [overlap ok] Ord a => Ord (Id a) instance [overlap ok] Show a => Show (Id a) instance [overlap ok] Eq Source instance [overlap ok] Ord Source instance [overlap ok] Show Source instance [overlap ok] Show Error instance [overlap ok] Eq DocOptional instance [overlap ok] Ord DocOptional instance [overlap ok] Show DocOptional instance [overlap ok] Read DocOptional instance [overlap ok] Eq Doc instance [overlap ok] Ord Doc instance [overlap ok] Show Doc instance [overlap ok] Read Doc instance [overlap ok] HasRenderDoc CommandLine instance [overlap ok] HasRenderDoc ShellEnv instance [overlap ok] HasRenderDoc ConfigFile instance [overlap ok] Typeable a => HasToDoc ('Type a) instance [overlap ok] HasToDoc a => HasToDoc ('Option a) instance [overlap ok] HasToDoc a => HasToDoc ('List a) instance [overlap ok] (HasToDoc a, KnownSymbol path, KnownSymbol descr) => HasToDoc ('Descr ('Label path a) descr) instance [overlap ok] (KnownSymbol path, HasToDoc a) => HasToDoc ('Label path a) instance [overlap ok] (HasToDoc a, HasToDoc b) => HasToDoc ('Record a b) instance [overlap ok] CanonicalizePartial ('Type a) instance [overlap ok] (cfg ~ 'Option cfg', CanonicalizePartial cfg') => CanonicalizePartial ('Option cfg') instance [overlap ok] (cfg ~ 'List cfg', CanonicalizePartial cfg') => CanonicalizePartial ('List cfg') instance [overlap ok] (cfg ~ 'Descr cfg' s, CanonicalizePartial cfg') => CanonicalizePartial ('Descr cfg' s) instance [overlap ok] (cfg ~ 'Label s cfg', CanonicalizePartial cfg') => CanonicalizePartial ('Label s cfg') instance [overlap ok] (CanonicalizePartial cfg, CanonicalizePartial cfg') => CanonicalizePartial ('Record cfg cfg') instance [overlap ok] Freeze ('Type c) instance [overlap ok] (ToConfig ('Option c) Maybe ~ MaybeO tm, ToConfig ('Option c) Id ~ MaybeO ti, tm ~ ToConfig c Maybe, ti ~ ToConfig c Id, Freeze c) => Freeze ('Option c) instance [overlap ok] Freeze c => Freeze ('List c) instance [overlap ok] (ToConfig ('Descr t s) Maybe ~ ToConfig t Maybe, ToConfig ('Descr t s) Id ~ ToConfig t Id, Freeze t) => Freeze ('Descr t s) instance [overlap ok] (KnownSymbol s, Freeze t) => Freeze ('Label s t) instance [overlap ok] (Freeze a, Freeze b) => Freeze ('Record a b) instance [overlap ok] Monoid (TaggedM a) => Monoid (TaggedM ('Option a)) instance [overlap ok] Monoid (TaggedM ('List a)) instance [overlap ok] Monoid (TaggedM ('Label s ('Type a))) instance [overlap ok] (ToConfig ('Descr a s) Maybe ~ ToConfig a Maybe, ToConfig a Maybe ~ Maybe a', Monoid (TaggedM a)) => Monoid (TaggedM ('Descr a s)) instance [overlap ok] Monoid (TaggedM a) => Monoid (TaggedM ('Label s a)) instance [overlap ok] (Monoid (TaggedM a), Monoid (TaggedM b)) => Monoid (TaggedM ('Record a b)) instance [overlap ok] ToVal cfg (p : ps) ~ 'Nothing => Sel' cfg (p : ps) instance [overlap ok] (t ~ ToConfig cfg Id, ToVal cfg '[] ~ 'Just t) => Sel' cfg '[] instance [overlap ok] Sel' cfg ps => Sel cfg ps instance [overlap ok] (cfg ~ 'Option cfg', NothingValue (ToVal cfg' ps), Sel cfg' ps) => Sel ('Option cfg') ps instance [overlap ok] (cfg ~ 'Descr cfg' s, Sel cfg' ps, ToConfig ('Descr cfg' s) Id ~ ToConfig cfg' Id) => Sel ('Descr cfg' s) ps instance [overlap ok] (cfg ~ 'Label p cfg', Sel cfg' ps, KnownSymbol p) => Sel ('Label p cfg') (p : ps) instance [overlap ok] (cfg ~ 'Record cfg' cfg'', Sel cfg' (p : ps), Sel cfg'' (p : ps)) => Sel ('Record cfg' cfg'') (p : ps) instance [overlap ok] Sel ('Record cfg' cfg'') '[] instance [overlap ok] NothingValue ('Just x) instance [overlap ok] NothingValue 'Nothing instance [overlap ok] HasParseShellEnv cfg => HasParseCommandLine cfg instance [overlap ok] (Typeable a, FromJSON (TaggedM ('Type a))) => HasParseShellEnv ('Type a) instance [overlap ok] HasParseShellEnv a => HasParseShellEnv ('Option a) instance [overlap ok] HasParseShellEnv a => HasParseShellEnv ('List a) instance [overlap ok] (ToConfig ('Descr cfg s) Maybe ~ ToConfig cfg Maybe, HasParseShellEnv cfg) => HasParseShellEnv ('Descr cfg s) instance [overlap ok] (KnownSymbol path, HasParseShellEnv a) => HasParseShellEnv ('Label path a) instance [overlap ok] (HasParseShellEnv a, HasParseShellEnv b) => HasParseShellEnv ('Record a b) instance [overlap ok] FromJSON a => FromJSON (TaggedM ('Type a)) instance [overlap ok] FromJSON (TaggedM cfg) => FromJSON (TaggedM ('Option cfg)) instance [overlap ok] FromJSON (TaggedM cfg) => FromJSON (TaggedM ('List cfg)) instance [overlap ok] (ToConfig ('Descr cfg s) Maybe ~ ToConfig cfg Maybe, FromJSON (TaggedM cfg)) => FromJSON (TaggedM ('Descr cfg s)) instance [overlap ok] (FromJSON (TaggedM cfg), KnownSymbol s) => FromJSON (TaggedM ('Label s cfg)) instance [overlap ok] (FromJSON (TaggedM cfg1), FromJSON (TaggedM cfg2)) => FromJSON (TaggedM ('Record cfg1 cfg2)) instance [overlap ok] ToJSON a => ToJSON (TaggedM ('Type a)) instance [overlap ok] (t ~ ToConfig cfg Maybe, ToConfig ('Option cfg) Maybe ~ MaybeO t'', ToJSON (TaggedM cfg)) => ToJSON (TaggedM ('Option cfg)) instance [overlap ok] (t ~ ToConfig cfg Maybe, ToJSON (TaggedM cfg)) => ToJSON (TaggedM ('List cfg)) instance [overlap ok] (ToConfig ('Descr cfg s) Maybe ~ ToConfig cfg Maybe, ToJSON (TaggedM cfg)) => ToJSON (TaggedM ('Descr cfg s)) instance [overlap ok] (ToJSON (TaggedM cfg), KnownSymbol s) => ToJSON (TaggedM ('Label s cfg)) instance [overlap ok] (t1 ~ ToConfig cfg1 Maybe, ToJSON (TaggedM cfg1), t2 ~ ToConfig cfg2 Maybe, ToJSON (TaggedM cfg2)) => ToJSON (TaggedM ('Record cfg1 cfg2)) instance [overlap ok] Exception Error instance [overlap ok] Show (ToConfig cfg Maybe) => Show (TaggedM cfg) instance [overlap ok] Show (ToConfig cfg Id) => Show (Tagged cfg) instance [overlap ok] Eq (ToConfig cfg Maybe) => Eq (TaggedM cfg) instance [overlap ok] Eq (ToConfig cfg Id) => Eq (Tagged cfg)